| /*===-- Lexer.l - Scanner for Stacker language -----------------*- C++ -*--===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file was developed by Reid Spencer and donated to the LLVM research |
| // group and is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file implements the flex scanner for Stacker languages files. |
| // |
| //===----------------------------------------------------------------------===*/ |
| |
| %option prefix="Stacker" |
| %option yylineno |
| %option nostdinit |
| %option never-interactive |
| %option batch |
| %option noyywrap |
| %option nodefault |
| %option 8bit |
| %option outfile="Lexer.cpp" |
| %option ecs |
| %option noreject |
| %option noyymore |
| |
| %{ |
| |
| #include "StackerCompiler.h" |
| #include "StackerParser.h" |
| |
| /* Conversion of text ints to binary */ |
| static int64_t IntToVal(const char *Buffer) { |
| int64_t Result = 0; |
| for (; *Buffer; Buffer++) { |
| int64_t OldRes = Result; |
| Result *= 10; |
| Result += *Buffer-'0'; |
| if (Result < OldRes) // Uh, oh, overflow detected!!! |
| StackerCompiler::ThrowException("constant bigger than 64 bits detected!"); |
| } |
| return Result; |
| } |
| |
| /* Conversion of text hexadecimal ints to binary */ |
| static int64_t HexIntToVal(const char *Buffer) { |
| int64_t Result = 0; |
| for (; *Buffer; ++Buffer) { |
| int64_t OldRes = Result; |
| Result *= 16; |
| char C = *Buffer; |
| if (C >= '0' && C <= '9') |
| Result += C-'0'; |
| else if (C >= 'A' && C <= 'F') |
| Result += C-'A'+10; |
| else if (C >= 'a' && C <= 'f') |
| Result += C-'a'+10; |
| |
| if (Result < OldRes) // Uh, oh, overflow detected!!! |
| StackerCompiler::ThrowException("constant bigger than 64 bits detected!"); |
| } |
| return Result; |
| } |
| |
| #define YY_NEVER_INTERACTIVE 1 |
| %} |
| |
| /* Comments start with a ; and go till end of line */ |
| Comment1 [#].*$ |
| /* You can also embed them in ( ... ) */ |
| Comment2 \(.*\) |
| /* We ignore white space */ |
| White [ \t\r\n] |
| |
| /* jdentifiers start with a % sign */ |
| Identifier [A-Za-z][-A-Za-z0-9_]* |
| |
| /* Strings can contain any character except " and \ */ |
| String \"[^\"]*\" |
| |
| /* Positive and negative integer constants*/ |
| PInteger [+]?[0-9]+ |
| NInteger -[0-9]+ |
| HexInteger 0x[0-9A-Fa-f]+ |
| |
| /* Special Characters - name them to avoid flex confusion */ |
| Semi [;] |
| Colon [:] |
| Less \< |
| More \> |
| LessEq \<\= |
| MoreEq \>\= |
| NotEq \<\> |
| Equal \= |
| Plus \+ |
| Minus \- |
| Incr \+\+ |
| Decr \-\- |
| Mult \* |
| Div \/ |
| StarSlash \*\/ |
| LShift \<\< |
| RShift \>\> |
| InStr \<s |
| InNum \<d |
| InChar \<c |
| OutStr \>s |
| OutNum \>d |
| OutChar \>c |
| |
| %% |
| |
| {Comment1} { /* Ignore comments */ } |
| {Comment2} { /* Ignore comments */ } |
| |
| {Colon} { return COLON; } |
| {Semi} { return SEMI; } |
| |
| TRUE { return TRUETOK; } |
| FALSE { return FALSETOK; } |
| ON { return TRUETOK; } |
| OFF { return FALSETOK; } |
| {Less} { return LESS; } |
| LT { return LESS; } |
| {More} { return MORE; } |
| GT { return MORE; } |
| {LessEq} { return LESS_EQUAL; } |
| LE { return LESS_EQUAL; } |
| {MoreEq} { return MORE_EQUAL; } |
| GE { return MORE_EQUAL; } |
| {NotEq} { return NOT_EQUAL; } |
| NE { return NOT_EQUAL; } |
| {Equal} { return EQUAL; } |
| EQ { return EQUAL; } |
| |
| {Plus} { return PLUS; } |
| {Minus} { return MINUS; } |
| {Incr} { return INCR; } |
| {Decr} { return DECR; } |
| {Mult} { return MULT; } |
| {Div} { return DIV; } |
| MOD { return MODULUS; } |
| NEG { return NEGATE; } |
| ABS { return ABS; } |
| MIN { return MIN; } |
| MAX { return MAX; } |
| {StarSlash} { return STAR_SLASH; } |
| |
| AND { return AND; } |
| OR { return OR; } |
| XOR { return XOR; } |
| {LShift} { return LSHIFT; } |
| {RShift} { return RSHIFT; } |
| |
| DROP { return DROP; } |
| NIP { return NIP; } |
| DUP { return DUP; } |
| SWAP { return SWAP; } |
| OVER { return OVER; } |
| PICK { return PICK; } |
| SELECT { return SELECT; } |
| ROT { return ROT; } |
| RROT { return RROT; } |
| ROLL { return ROLL; } |
| TUCK { return TUCK; } |
| DROP2 { return DROP2; } |
| NIP2 { return NIP2; } |
| DUP2 { return DUP2; } |
| SWAP2 { return SWAP2; } |
| OVER2 { return OVER2; } |
| TUCK2 { return TUCK2; } |
| ROT2 { return ROT2; } |
| RROT2 { return RROT2; } |
| |
| MALLOC { return MALLOC; } |
| FREE { return FREE; } |
| GET { return GET; } |
| PUT { return PUT; } |
| |
| IF { return IF; } |
| ELSE { return ELSE; } |
| ENDIF { return ENDIF; } |
| WHILE { return WHILE; } |
| END { return END; } |
| |
| RECURSE { return RECURSE; } |
| RETURN { return RETURN; } |
| EXIT { return EXIT; } |
| FORWARD { return FORWARD; } |
| TAB { return TAB; } |
| SPACE { return SPACE; } |
| CR { return CR; } |
| |
| {InStr} { return IN_STR; } |
| {InNum} { return IN_NUM; } |
| {InChar} { return IN_CHAR; } |
| |
| {OutStr} { return OUT_STR; } |
| {OutNum} { return OUT_NUM; } |
| {OutChar} { return OUT_CHAR; } |
| |
| MAIN { return MAIN; } |
| |
| DUMP { return DUMP; } |
| |
| != { StackerCompiler::ThrowException( |
| "You probably meant to use a <> instead of !=" ); } |
| |
| == { StackerCompiler::ThrowException( |
| "You probably meant to use a single = .. this isn't C"); } |
| |
| {PInteger} { Stackerlval.IntegerVal = IntToVal(yytext); return INTEGER; } |
| {NInteger} { uint64_t Val = IntToVal(yytext+1); |
| // +1: we have bigger negative range |
| if (Val > (uint64_t)INT64_MAX+1) |
| StackerCompiler::ThrowException( |
| "Constant too large for signed 64 bits!"); |
| Stackerlval.IntegerVal = -Val; |
| return INTEGER; |
| } |
| {HexInteger} { Stackerlval.IntegerVal = HexIntToVal(yytext+3); |
| return INTEGER; |
| } |
| |
| {String} { yytext[strlen(yytext)-1] = 0; // nuke end quote |
| Stackerlval.StringVal = strdup(yytext+1); // Nuke start quote |
| return STRING; |
| } |
| |
| {Identifier} { Stackerlval.StringVal = strdup(yytext); return IDENTIFIER; } |
| |
| {White} { /* Ignore whitespace */ } |
| %% |