A "high-level" language for the Gameboy
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

56 lines
1.4 KiB

  1. // AST factories
  2. {
  3. const attr = (name, args) => ({ name, args })
  4. const stmt = (stmt_type, args) => ({ type: "stmt", stmt_type, args })
  5. const decl = (decl_type, args) => ({ type: "decl", decl_type, args })
  6. }
  7. Program = WS @(Decl / Stmt)* WS
  8. // Declarations
  9. Decl = VarDecl
  10. VarDecl = Attrs? type:Type name:Ident SEMI { return decl("var", { type, name }) }
  11. // Statements
  12. Stmt = @AssignStmt SEMI
  13. AssignStmt = name:Ident ASSIGN expr:Expr { return stmt("assign", { name, expr }) }
  14. // Expr
  15. Expr = BaseExpr
  16. BaseExpr = Number
  17. // Primitive types
  18. Type = PrimitiveType
  19. PrimitiveType = S8 / U8 / U16
  20. // Attributes
  21. Attrs = LATTR @AttrList RATTR
  22. AttrList = h:Attr t:(COMMA @Attr)* { return [h].concat(t) }
  23. / '' { return [] }
  24. Attr = name:Ident args:(LPAREN @AttrArgs RPAREN)? { return attr(name, args || []) }
  25. AttrArgs = h:AttrArg t:(COMMA @AttrArg)* { return [h].concat(t) }
  26. / '' { return [] }
  27. AttrArg = Ident / Number
  28. // Terminals
  29. Ident = h:[a-zA-Z_] t:[0-9a-zA-Z_]* WS { return h + t.join('') }
  30. Number = digits:[0-9]+ WS { return parseInt(digits.join(''), 10) }
  31. / '0x' digits:[a-fA-F0-9]+ WS { return parseInt(digits.join(''), 16) }
  32. / '0b' digits:[01]+ WS { return parseInt(digits.join(''), 2) }
  33. // Terminal keywords
  34. S8 = @'s8' WS
  35. U8 = @'u8' WS
  36. U16 = @'u16' WS
  37. // Terminal symbols
  38. SEMI = ';' WS
  39. ASSIGN = '<-' WS
  40. LPAREN = '(' WS
  41. RPAREN = ')' WS
  42. COMMA = ',' WS
  43. LATTR = '[[' WS
  44. RATTR = ']]' WS
  45. // Misc
  46. WS = [ \t\r\n]*