Skip to content

Instantly share code, notes, and snippets.

@rikkimax
Last active May 21, 2016 13:34
Show Gist options
  • Save rikkimax/160547d2fba5042e0893f9dd03a3d4ff to your computer and use it in GitHub Desktop.
Save rikkimax/160547d2fba5042e0893f9dd03a3d4ff to your computer and use it in GitHub Desktop.
module dcf.phase1;
import std.range.interfaces : InputRange;
final class DCFPhase1 : InputRange!char {
private {
InputRange!char source;
char next;
byte bufLeft;
char[3] buf;
}
this(InputRange!char source) {
this.source = source;
popFront;
}
@property {
bool empty() {
return source.empty && bufLeft == 0;
}
char front() {
return next;
}
}
char moveFront() {
scope(exit) popFront;
return next;
}
void popFront() {
if (bufLeft == -1) {
bufLeft = 0;
return;
}
// ensures our buffer is as full as it can be
while(bufLeft < 3 && !source.empty) {
if (bufLeft == 2) {
buf[2] = source.front;
source.popFront;
bufLeft = 3;
} else if (bufLeft == 1) {
buf[1] = source.front;
source.popFront;
bufLeft = 2;
} else if (bufLeft == 0) {
buf[0] = source.front;
source.popFront;
bufLeft = 1;
}
}
void replaceDigraph(char v) {
buf[0] = v;
if (bufLeft == 3) {
buf[1] = buf[2];
bufLeft = 2;
} else if (bufLeft == 2)
bufLeft = 1;
}
if (bufLeft >= 2) {
switch(buf[0 .. 2]) {
case ['<', '%']:
replaceDigraph('{');
break;
case ['%', '>']:
replaceDigraph('}');
break;
case ['<', ':']:
replaceDigraph('[');
break;
case [':', '>']:
replaceDigraph(']');
break;
case ['%', ':']:
replaceDigraph('#');
break;
case ['\r', '\n']:
replaceDigraph('\n');
break;
case ['\n', '\r']:
replaceDigraph('\n');
break;
default:
break;
}
}
void replaceTrigraph(char v) {
buf[0] = v;
bufLeft = 1;
}
if (bufLeft == 3) {
switch(buf) {
case ['?', '?', '<']:
replaceTrigraph('{');
break;
case ['?', '?', '>']:
replaceTrigraph('}');
break;
case ['?', '?', '(']:
replaceTrigraph('[');
break;
case ['?', '?', ')']:
replaceTrigraph(']');
break;
case ['?', '?', '=']:
replaceTrigraph('#');
break;
case ['?', '?', '/']:
replaceTrigraph('\\');
break;
case ['?', '?', '\'']:
replaceTrigraph('^');
break;
case ['?', '?', '!']:
replaceTrigraph('|');
break;
case ['?', '?', '-']:
replaceTrigraph('~');
break;
default:
break;
}
}
if (bufLeft > 0) {
next = buf[0];
bufLeft--;
}
if (bufLeft == 1) {
buf[0] = buf[1];
} else if (bufLeft == 2) {
buf[0] = buf[1];
buf[1] = buf[2];
}
if (source.empty && bufLeft == 0)
bufLeft = -1;
}
int opApply(int delegate(char) dg) @trusted {
int result = 0;
while(!empty) {
result = dg(front);
popFront;
if (result)
break;
}
return result;
}
int opApply(int delegate(size_t i, char) dg) @trusted {
int result = 0;
size_t i;
while(!empty) {
result = dg(i, front);
popFront;
if (result)
break;
i++;
}
return result;
}
}
unittest {
import dcf.defs : stringInputRange;
import std.algorithm : equal;
string input = """
%:include <stdlib.h>
%:include <stdio.h>
%:include <iso646.h>
int main(int argc, char** argv)
??<
if (argc > 1 and argv<:1:> not_eq NULL)
<%
printf(\"Hello%s\\n\", argv<:1:>);
%>
return EXIT_SUCCESS;
??>
""";
DCFPhase1 range = new DCFPhase1(input.stringInputRange);
assert(range.equal("""
#include <stdlib.h>
#include <stdio.h>
#include <iso646.h>
int main(int argc, char** argv)
{
if (argc > 1 and argv[1] not_eq NULL)
{
printf(\"Hello%s\\n\", argv[1]);
}
return EXIT_SUCCESS;
}
"""));
}
module alphacodegen.lang_d.test;
void main() {
import alphacodegen.common.lang.defs;
final class Token : IToken {
TokenIdentifier tokenId;
dstring text;
@property {
TokenIdentifier tokenIdentifier() {
return tokenId;
}
const(dchar[]) tokenText() {
return text;
}
}
}
alias Lex = LexicalPhaseGenerator!(() {
LexicalPhaseConfig config;
config.tokenCreator = q{
auto ret = new Token;
ret.tokenId = identifier;
return ret;
};
config.errorHandler = q{
//throw new Exception("ICE: " ~ errorMessage);
};
config.enable_c_singleline_comment = true;
config.enable_c_multiline_comment = true;
config.enable_D_multiline_comment = true;
config.enable_number_negative = true;
config.enable_number_floating = true;
config.enable_number_decimal = true;
config.enable_number_hexadecimal = true;
config.enable_number_octal = true;
config.enable_string_array = true;
config.enable_c_u8_stringhint = true;
config.enable_c_header_string = true;
config.enable_c_string_u = true;
config.enable_c_string_U = true;
config.enable_c_string_L = true;
config.enable_char_literal = true;
config.enable_c_char_u = true;
config.enable_c_char_U = true;
config.enable_c_char_L = true;
return config;
}(), char[], Token);
Lex lexer;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment