compiler/libec2: Initial go at a handwritten Recursive Descent parser
[sdk] / compiler / libec2 / src / lexing.ec
1 public import "ecere"
2 public import "ec"
3
4 public enum TokenType
5 {
6    IDENTIFIER = 258, CONSTANT = 259, STRING_LITERAL = 260, SIZEOF = 261,PTR_OP = 262,INC_OP = 263,DEC_OP = 264, LEFT_OP = 265, RIGHT_OP = 266, LE_OP = 267, GE_OP = 268, EQ_OP = 269, NE_OP = 270,
7    AND_OP = 271, OR_OP = 272, MUL_ASSIGN = 273, DIV_ASSIGN = 274, MOD_ASSIGN = 275, ADD_ASSIGN = 276, SUB_ASSIGN = 277, LEFT_ASSIGN = 278, RIGHT_ASSIGN = 279, AND_ASSIGN = 280, XOR_ASSIGN = 281,
8    OR_ASSIGN = 282, TYPE_NAME = 283, TYPEDEF = 284, EXTERN = 285, STATIC = 286, AUTO = 287, REGISTER = 288, CHAR = 289, SHORT = 290, INT = 291, UINT = 292, INT64 = 293, LONG = 294, SIGNED = 295,
9    UNSIGNED = 296, FLOAT = 297, DOUBLE = 298, CONST = 299, VOLATILE = 300, VOID = 301, VALIST = 302, STRUCT = 303, UNION = 304, ENUM = 305, ELLIPSIS = 306, CASE = 307, DEFAULT = 308, IF = 309,
10    SWITCH = 310, WHILE = 311, DO = 312, FOR = 313, GOTO = 314, CONTINUE = 315, BREAK = 316, RETURN = 317, IFX = 318, ELSE = 319, CLASS = 320, THISCLASS = 321, CLASS_NAME = 322, PROPERTY = 323,
11    SETPROP = 324, GETPROP = 325, NEWOP = 326, RENEW = 327, DELETE = 328, EXT_DECL = 329, EXT_STORAGE = 330, IMPORT = 331, DEFINE = 332, VIRTUAL = 333, ATTRIB = 334, PUBLIC = 335, PRIVATE = 336,
12    TYPED_OBJECT = 337, ANY_OBJECT = 338, _INCREF = 339, EXTENSION = 340, ASM = 341, TYPEOF = 342, WATCH = 343, STOPWATCHING = 344, FIREWATCHERS = 345, WATCHABLE = 346, CLASS_DESIGNER = 347,
13    CLASS_NO_EXPANSION = 348, CLASS_FIXED = 349, ISPROPSET = 350, CLASS_DEFAULT_PROPERTY = 351, PROPERTY_CATEGORY = 352, CLASS_DATA = 353, CLASS_PROPERTY = 354, SUBCLASS = 355, NAMESPACE = 356,
14    NEW0OP = 357, RENEW0 = 358, VAARG = 359, DBTABLE = 360, DBFIELD = 361, DBINDEX = 362, DATABASE_OPEN = 363, ALIGNOF = 364, ATTRIB_DEP = 365, __ATTRIB = 366;
15
16    property char { }
17
18    property bool isUnaryOperator
19    {
20       get
21       {
22          return this == '&' || this == '*' || this == '+' || this == '-' || this == '~' || this == '!' || this == DELETE || this == _INCREF;
23       }
24    }
25
26    property bool isAssignmentOperator
27    {
28       get
29       {
30           return this == '='|| this == MUL_ASSIGN || this == DIV_ASSIGN || this == MOD_ASSIGN ||
31                this == ADD_ASSIGN || this == SUB_ASSIGN || this == LEFT_ASSIGN || this == RIGHT_ASSIGN ||
32                this == AND_ASSIGN || this == XOR_ASSIGN || this == OR_ASSIGN;
33       }
34    }
35
36    void print()
37    {
38       if(this < 256)
39          Print((char)this);
40       else
41       {
42          switch(this)
43          {
44             case VOID: Print("void"); break;
45             case CHAR:  Print("char");  break;
46             case SHORT:  Print("short");  break;
47             case INT:  Print("int");  break;
48             case LONG:  Print("long");  break;
49             case INT64:  Print("int64");  break;
50             case UNSIGNED:  Print("unsigned");  break;
51             case SIGNED:  Print("signed");  break;
52             case FLOAT:  Print("float");  break;
53             case DOUBLE:  Print("double");  break;
54
55             case INC_OP: Print("++"); break;
56             case DEC_OP: Print("--"); break;
57             case SIZEOF: Print("sizeof "); break;
58             case LEFT_OP: Print("<<"); break;
59             case RIGHT_OP: Print(">>"); break;
60             case LE_OP: Print("<="); break;
61             case GE_OP: Print(">="); break;
62             case EQ_OP: Print("=="); break;
63             case NE_OP: Print("!="); break;
64             case AND_OP: Print("&&"); break;
65             case OR_OP: Print("||"); break;
66            case MUL_ASSIGN: Print("*="); break;
67            case DIV_ASSIGN: Print("/="); break;
68            case MOD_ASSIGN: Print("%="); break;
69            case ADD_ASSIGN: Print("+="); break;
70            case SUB_ASSIGN: Print("-="); break;
71            case LEFT_ASSIGN: Print("<<="); break;
72            case RIGHT_ASSIGN: Print(">>="); break;
73            case AND_ASSIGN: Print("&="); break;
74            case XOR_ASSIGN: Print("^="); break;
75            case OR_ASSIGN: Print("|="); break;
76          }
77       }
78    }
79 };
80
81 class Token
82 {
83    TokenType type;
84    String text;
85    ~Token()
86    {
87       delete text;
88    }
89 }
90
91 Token token, nextToken;
92
93 int ambiguous, stackPos;
94 Array<Token> tokenStack { minAllocSize = 256 };
95
96 Token readToken()
97 {
98    if(!nextToken) peekToken();
99    delete token;
100    token = nextToken;
101    nextToken = null;
102    return token;
103 }
104
105 Token peekToken()
106 {
107    if(!nextToken)
108    {
109       if(stackPos < tokenStack.count)
110       {
111          nextToken = tokenStack[stackPos++];
112          incref nextToken;
113          if(!ambiguous && stackPos == tokenStack.count)
114          {
115             tokenStack.Free();
116             stackPos = 0;
117          }
118       }
119       else
120       {
121          nextToken = { _refCount = 1 };
122          nextToken.type = (TokenType)LexEc();
123          nextToken.text = CopyString(GetYYText());
124          if(ambiguous)
125          {
126             stackPos++;
127             tokenStack.Add(nextToken);
128             incref nextToken;
129          }
130       }
131    }
132    return nextToken;
133 }
134
135 int pushAmbiguity()
136 {
137    if(!ambiguous && nextToken && stackPos == tokenStack.count)
138    {
139       stackPos++;
140       tokenStack.Add(nextToken);
141       incref nextToken;
142    }
143    ambiguous++;
144    return stackPos - (nextToken ? 1 : 0);
145 }
146
147 void clearAmbiguity()
148 {
149    if(!--ambiguous && stackPos > 0)
150    {
151       int i;
152       for(i = 0; i < stackPos; i++)
153          delete tokenStack[i];
154       if(tokenStack.size > stackPos)
155          memmove(tokenStack.array, tokenStack.array + stackPos, (tokenStack.size - stackPos) * sizeof(Token));
156       tokenStack.size -= stackPos;
157       stackPos = 0;      
158    }
159 }
160
161 void popAmbiguity(int i)
162 {
163    delete token;
164    delete nextToken;
165
166    stackPos = i;
167    clearAmbiguity();
168    token = null;
169    nextToken = null;
170 }
171
172 public void lexAll()
173 {
174    while(readToken())
175    {
176       if(token.type < 256)
177          PrintLn((char)token.type);
178       else
179          PrintLn(token.type, " (", token.text, ")");
180    }
181 }
182
183 public void initParser(File f)
184 {
185    SetFileInput(f);
186    delete token;
187    delete nextToken;
188    tokenStack.size = 0;
189    stackPos = 0;
190    ambiguous = 0;
191 }