|
|
- // AST factories
- {
- const attr = (name, args) => ({ name, args })
- const stmt = (stmt_type, args) => ({ type: "stmt", stmt_type, args })
- const decl = (decl_type, name, attrs, args) => ({ type: "decl", decl_type, name, attrs: attrs || [], args })
- const uexpr = (op, arg) => ({ type: "unary", op, arg })
- const bexpr = (op, left, right) => ({ type: "binary", op, left, right })
-
- const assocl = (head, tail) => tail.reduce((left, arg) => {
- const [op, right] = arg
- return bexpr(op, left, right)
- }, head)
- }
-
- Program = WS @(Decl / Stmt)* WS
-
- // Declarations
- Decl = VarDecl
- VarDecl = attrs:Attrs? type:Type name:Ident SEMI { return decl("var", name, attrs, { type }) }
-
- // Statements
- Stmt = @AssignStmt SEMI
- AssignStmt = name:Ident ASSIGN expr:Expr { return stmt("assign", { name, expr }) }
-
- // Expressions
- Expr = BitOrExpr
-
- BitOrExpr = head:BitXorExpr tail:(op:BitOrOp e:BitXorExpr)* { return assocl(head, tail || []) }
- BitOrOp = PIPE { return "bit_or" }
-
- BitXorExpr = head:BitAndExpr tail:(op:BitXorOp e:BitAndExpr)* { return assocl(head, tail || []) }
- BitXorOp = CARET { return "bit_xor" }
-
- BitAndExpr = head:ShiftExpr tail:(op:BitAndOp e:ShiftExpr)* { return assocl(head, tail || []) }
- BitAndOp = AMPERSAND { return "bit_and" }
-
- ShiftExpr = head:AddExpr tail:(op:ShiftOp e:AddExpr)* { return assocl(head, tail || []) }
- ShiftOp = LTLT { return "shift_left" }
- / GTGT { return "shift_right" }
-
- AddExpr = head:UnaryExpr tail:(op:AddOp e:UnaryExpr)* { return assocl(head, tail || []) }
- AddOp = PLUS { return "add" }
- / MINUS { return "subtract" }
-
- UnaryExpr = op:UnaryOp? e:BaseExpr { return op ? uexpr(op, e) : e }
- UnaryOp = TILDE { return "bit_negate" }
- / MINUS { return "arith_negate" }
-
- BaseExpr = Ident / Number / LPAREN @Expr RPAREN
-
- // Attributes
- Attrs = LATTR @AttrList RATTR
- AttrList = h:Attr t:(COMMA @Attr)* { return [h].concat(t) }
- / '' { return [] }
- Attr = name:Ident args:(LPAREN @AttrArgs RPAREN)? { return attr(name, args || []) }
- AttrArgs = h:AttrArg t:(COMMA @AttrArg)* { return [h].concat(t) }
- / '' { return [] }
- AttrArg = Ident / Number
-
- // Types
- Type = PrimitiveType
- PrimitiveType = S8 / U8 / U16
-
- // Terminals
- Ident = h:[a-zA-Z_] t:[0-9a-zA-Z_]* WS { return h + t.join('') }
- Number = digits:[0-9]+ WS { return parseInt(digits.join(''), 10) }
- / '0x' digits:[a-fA-F0-9]+ WS { return parseInt(digits.join(''), 16) }
- / '0b' digits:[01]+ WS { return parseInt(digits.join(''), 2) }
-
- // Terminal keywords
- S8 = @'s8' WS
- U8 = @'u8' WS
- U16 = @'u16' WS
-
- // Terminal symbols
- PIPE = '|' WS
- CARET = '^' WS
- AMPERSAND = '&' WS
- LTLT = '<<' WS
- GTGT = '>>' WS
- PLUS = '+' WS
- TILDE = '~' WS
- MINUS = '-' WS
- SEMI = ';' WS
- ASSIGN = '<-' WS
- LPAREN = '(' WS
- RPAREN = ')' WS
- COMMA = ',' WS
- LATTR = '[[' WS
- RATTR = ']]' WS
-
- // Misc
- WS = [ \t\r\n]*
|