|
29 | 29 | '''
|
30 | 30 |
|
31 | 31 | import sly
|
| 32 | +import sys |
| 33 | + |
| 34 | +# dictionaries got insertion order in 3.6, guaranteed in 3.7 |
| 35 | +assert sys.version_info >= (3, 6) |
32 | 36 |
|
33 | 37 | # TODO(ahuszagh) Implement...
|
34 | 38 |
|
|
41 | 45 | _ESCAPE = r'{_UNICODE}|\\[^\r\n\f0-9a-f]'
|
42 | 46 |
|
43 | 47 | class Lexer(sly.Lexer):
|
44 |
| - tokens = { BOOL, NUMBER, IDENT, STRING } |
| 48 | + tokens = { |
| 49 | + BOOL, |
| 50 | + FLOAT, |
| 51 | + INTEGER, |
| 52 | + IDENT, |
| 53 | + STRING, |
| 54 | + LBRACKET, |
| 55 | + RBRACKET, |
| 56 | + LBRACE, |
| 57 | + RBRACE, |
| 58 | + COLON, |
| 59 | + COMMA, |
| 60 | + EQUALS, |
| 61 | + } |
45 | 62 | ignore = ' \t'
|
46 |
| - literals = { '[', ']', '{', '}', ':', ',', '=' } |
47 | 63 |
|
48 | 64 | # Tokens
|
| 65 | + # TODO(ahuszagh) Fix... |
49 | 66 | STRING = fr'"([^\n\r\f\\"]|\\{_NL}|{_ESCAPE})*"'
|
50 |
| - NUMBER = r'(?:\d+\.\d*)|(?:\.\d+)|(?:\d+)' |
| 67 | + FLOAT = r'(?:\d+\.\d*)|(?:\.\d+)' |
| 68 | + INTEGER = r'\d+' |
51 | 69 | BOOL = '(?:true)|(?:false)'
|
52 | 70 | IDENT = r'[a-zA-Z_][a-zA-Z0-9_]*'
|
| 71 | + LBRACKET = r'\[' |
| 72 | + RBRACKET = r'\]' |
| 73 | + LBRACE = r'\{' |
| 74 | + RBRACE = r'\}' |
| 75 | + COLON = r':' |
| 76 | + COMMA = r',' |
| 77 | + EQUALS = r'=' |
53 | 78 |
|
54 | 79 | @_(r'\n+')
|
55 | 80 | def newline(self, t):
|
@@ -82,56 +107,220 @@ class Parser(sly.Parser):
|
82 | 107 | # )
|
83 | 108 | #
|
84 | 109 | def __init__(self):
|
85 |
| - self.ast = Ast([]) |
86 |
| - |
87 |
| - @_('IDENT "=" expr') |
88 |
| - def assign(self, p): |
89 |
| - import pdb; pdb.set_trace() |
90 |
| - self.names[p.NAME] = p.expr |
| 110 | + self.ast = Ast() |
91 | 111 |
|
92 |
| -# @_('expr') |
93 |
| -# def statement(self, p): |
94 |
| -# print(p.expr) |
95 |
| -# |
96 |
| -# @_('expr "+" expr') |
97 |
| -# def expr(self, p): |
98 |
| -# return p.expr0 + p.expr1 |
| 112 | +# @_('list COMMA basic_type') |
| 113 | +# def list(self, p): |
| 114 | +# import pdb; pdb.set_trace() |
99 | 115 | #
|
100 |
| -# @_('expr "-" expr') |
101 |
| -# def expr(self, p): |
102 |
| -# return p.expr0 - p.expr1 |
103 |
| -# |
104 |
| -# @_('expr "*" expr') |
105 |
| -# def expr(self, p): |
106 |
| -# return p.expr0 * p.expr1 |
107 |
| -# |
108 |
| -# @_('expr "/" expr') |
109 |
| -# def expr(self, p): |
110 |
| -# return p.expr0 / p.expr1 |
| 116 | +# @_('basic_type COMMA') |
| 117 | +# def list(self, p): |
| 118 | +# import pdb; pdb.set_trace() |
| 119 | + |
| 120 | +# TODO(ahuszagh) I thought this group worked... |
| 121 | + |
| 122 | +# @_('ident LBRACE map RBRACE') |
| 123 | +# def object(self, p): |
| 124 | +# return Variable(p[0], p[1]) |
111 | 125 | #
|
112 |
| -# @_('"-" expr %prec UMINUS') |
113 |
| -# def expr(self, p): |
114 |
| -# return -p.expr |
| 126 | +# def map(self, p): |
| 127 | +# pass |
| 128 | + |
| 129 | + @_('variable') |
| 130 | + def rule(self, p): |
| 131 | + self.ast.append(p[0]) |
| 132 | + |
| 133 | + @_('scope') |
| 134 | + def rule(self, p): |
| 135 | + import pdb; pdb.set_trace() |
| 136 | + self.ast.append(p[0]) |
| 137 | + |
| 138 | + @_('ident EQUALS expr') |
| 139 | + def variable(self, p): |
| 140 | + return Variable(p[0], p[1]) |
| 141 | + |
| 142 | + @_('ident LBRACE object RBRACE') |
| 143 | + def scope(self, p): |
| 144 | + return Scope(p[0], Object(p[2])) |
| 145 | + |
| 146 | + @_('ident LBRACE object COMMA RBRACE') |
| 147 | + def scope(self, p): |
| 148 | + return Scope(p[0], Object(p[2])) |
| 149 | + |
| 150 | + @_('object COMMA pair') |
| 151 | + def object(self, p): |
| 152 | + return p[0] + [p[2]] |
| 153 | + |
| 154 | + @_('pair') |
| 155 | + def object(self, p): |
| 156 | + return [p[0]] |
| 157 | + |
| 158 | + @_('ident COLON expr') |
| 159 | + def pair(self, p): |
| 160 | + return (p[0], p[2]) |
| 161 | + |
| 162 | + @_('array') |
| 163 | + def expr(self, p): |
| 164 | + return Expr(p[0]) |
| 165 | + |
| 166 | + @_('basic_type') |
| 167 | + def expr(self, p): |
| 168 | + return Expr(p[0]) |
| 169 | + |
| 170 | + @_('LBRACKET basic_type RBRACKET') |
| 171 | + def array(self, p): |
| 172 | + return Array([p[1]]) |
| 173 | + |
| 174 | + @_('LBRACKET basic_type COMMA RBRACKET') |
| 175 | + def array(self, p): |
| 176 | + return Array([p[1]]) |
| 177 | + |
| 178 | + @_('LBRACKET sequence RBRACKET') |
| 179 | + def array(self, p): |
| 180 | + return Array(p[1]) |
| 181 | + |
| 182 | + @_('LBRACKET sequence COMMA RBRACKET') |
| 183 | + def array(self, p): |
| 184 | + return Array(p[1]) |
| 185 | + |
| 186 | + @_('sequence COMMA basic_type') |
| 187 | + def sequence(self, p): |
| 188 | + return p[0] + [p[2]] |
| 189 | + |
| 190 | + @_('basic_type COMMA basic_type') |
| 191 | + def sequence(self, p): |
| 192 | + return [p[0], p[2]] |
| 193 | + |
| 194 | + @_('IDENT') |
| 195 | + def ident(self, p): |
| 196 | + return Ident(p.IDENT) |
| 197 | + |
| 198 | + @_('STRING') |
| 199 | + def basic_type(self, p): |
| 200 | + return p.STRING |
| 201 | + |
| 202 | + @_('FLOAT') |
| 203 | + def basic_type(self, p): |
| 204 | + return Float(p.FLOAT) |
| 205 | + |
| 206 | + @_('INTEGER') |
| 207 | + def basic_type(self, p): |
| 208 | + return Integer(p.INTEGER) |
| 209 | + |
| 210 | + @_('BOOL') |
| 211 | + def basic_type(self, p): |
| 212 | + return Bool(p.BOOL) |
| 213 | + |
| 214 | +# @_('LBRACE') |
| 215 | +# def lbrace(self, p): |
| 216 | +# import pdb; pdb.set_trace() |
115 | 217 | #
|
116 |
| -# @_('"(" expr ")"') |
117 |
| -# def expr(self, p): |
118 |
| -# return p.expr |
| 218 | +# @_('RBRACE') |
| 219 | +# def rbrace(self, p): |
| 220 | +# import pdb; pdb.set_trace() |
119 | 221 | #
|
120 |
| -# @_('NUMBER') |
121 |
| -# def expr(self, p): |
122 |
| -# return p.NUMBER |
| 222 | +# @_('COLON') |
| 223 | +# def colon(self, p): |
| 224 | +# import pdb; pdb.set_trace() |
123 | 225 | #
|
124 |
| -# @_('NAME') |
125 |
| -# def expr(self, p): |
126 |
| -# try: |
127 |
| -# return self.names[p.NAME] |
128 |
| -# except LookupError: |
129 |
| -# print("Undefined name '%s'" % p.NAME) |
130 |
| -# return 0 |
131 |
| - |
132 |
| -class Ast: |
133 |
| - def __init__(self, nodes): |
134 |
| - self.nodes = nodes |
135 |
| - |
136 |
| -class Node: |
| 226 | +# @_('EQUALS') |
| 227 | +# def equals(self, p): |
| 228 | +# import pdb; pdb.set_trace() |
| 229 | + |
| 230 | + # TODO(ahuszagh) Restore this |
| 231 | +# @_('IDENT "=" expr') |
| 232 | +# def assignment(self, p): |
| 233 | +# import pdb; pdb.set_trace() |
| 234 | +# self.names[p.IDENT] = p.expr |
| 235 | + |
| 236 | +## @_('expr') |
| 237 | +## def statement(self, p): |
| 238 | +## print(p.expr) |
| 239 | +## |
| 240 | +## @_('expr "+" expr') |
| 241 | +## def expr(self, p): |
| 242 | +## return p.expr0 + p.expr1 |
| 243 | +## |
| 244 | +## @_('expr "-" expr') |
| 245 | +## def expr(self, p): |
| 246 | +## return p.expr0 - p.expr1 |
| 247 | +## |
| 248 | +## @_('expr "*" expr') |
| 249 | +## def expr(self, p): |
| 250 | +## return p.expr0 * p.expr1 |
| 251 | +## |
| 252 | +## @_('expr "/" expr') |
| 253 | +## def expr(self, p): |
| 254 | +## return p.expr0 / p.expr1 |
| 255 | +## |
| 256 | +## @_('"-" expr %prec UMINUS') |
| 257 | +## def expr(self, p): |
| 258 | +## return -p.expr |
| 259 | +## |
| 260 | +## @_('"(" expr ")"') |
| 261 | +## def expr(self, p): |
| 262 | +## return p.expr |
| 263 | +## |
| 264 | +## @_('NUMBER') |
| 265 | +## def expr(self, p): |
| 266 | +## return p.NUMBER |
| 267 | +## |
| 268 | +## @_('NAME') |
| 269 | +## def expr(self, p): |
| 270 | +## try: |
| 271 | +## return self.names[p.NAME] |
| 272 | +## except LookupError: |
| 273 | +## print("Undefined name '%s'" % p.NAME) |
| 274 | +## return 0 |
| 275 | + |
| 276 | +class Ast(list): |
| 277 | + def __repr__(self): |
| 278 | + return '\n'.join(self) |
| 279 | + |
| 280 | +class Expr: |
| 281 | + def __init__(self, expr): |
| 282 | + self.expr = expr |
| 283 | + |
| 284 | + def __repr__(self): |
| 285 | + return f'{repr(self.expr)}' |
| 286 | + |
| 287 | +class Variable: |
| 288 | + def __init__(self, name, expr): |
| 289 | + self.name = name |
| 290 | + self.expr = expr |
| 291 | + |
| 292 | + def __repr__(self): |
| 293 | + return f'{repr(self.name)} = {repr(self.expr)}' |
| 294 | + |
| 295 | +class Scope: |
| 296 | + def __init__(self, name, obj): |
| 297 | + self.name = name |
| 298 | + self.obj = obj |
| 299 | + |
| 300 | + def __repr__(self): |
| 301 | + return f'{repr(self.name)} {repr(self.obj)}' |
| 302 | + |
| 303 | +class Object(dict): |
| 304 | + pass |
| 305 | + |
| 306 | +class Array(list): |
| 307 | + pass |
| 308 | + |
| 309 | +class Ident(str): |
| 310 | + pass |
| 311 | + |
| 312 | +class String(str): |
137 | 313 | pass
|
| 314 | + |
| 315 | +class Float(float): |
| 316 | + pass |
| 317 | + |
| 318 | +class Integer(int): |
| 319 | + pass |
| 320 | + |
| 321 | +class Bool: |
| 322 | + def __init__(self, value=False): |
| 323 | + self.value = value |
| 324 | + |
| 325 | + def __bool__(self): |
| 326 | + return self.value |
0 commit comments