Parser is responsible for parsing a list of tokens into the abstract syntax tree. At this point the CompilationUnit, Usings, and TypeDefs are already populated by the ScanForUsingAndTypes step.
Slots
- OnceSource
-
static Int Once := 2147483648
- ParserFlagsMaskSource
-
static Int ParserFlagsMask := Readonly
- ProtectionMaskSource
-
static Int ProtectionMask := ...
- ReadonlySource
-
static Int Readonly := 1073741824
-
private Expr additiveExpr()
Additive expression:
<addExpr> := <multExpr> (("+" | "-") <multExpr>)*
-
private Expr assignExpr(Expr? expr := null)
Assignment expression:
<assignExpr> := <condOrExpr> [<assignOp> <assignExpr>] <assignOp> := "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | "&=" | "^=" | "|="
-
private Expr bitAndExpr()
Bitwise and expression:
<bitAndExpr> := <shiftExpr> (("&" <shiftExpr>)*
-
private Expr bitOrExpr()
Bitwise or expression:
<bitOrExpr> := <bitAndExpr> (("^" | "|") <bitAndExpr>)*
-
private Block block(Bool inVoid)
Top level for blocks which must be surrounded by braces
-
private BreakStmt breakStmt()
Break statement:
<break> := "break" <eos>
-
private Void callArgs(CallExpr call)
Parse args with known parens:
<args> := [<expr> ("," <expr>)*] [<closure>]
-
private CallExpr callExpr(Expr? target)
Call expression:
<call> := <id> ["(" <args> ")"] [<closure>]
-
private Expr callOp(Expr target)
Call operator:
<callOp> := "(" <args> ")" [<closure>]
-
private ClosureExpr closure(Location loc, FuncType funcType)
Parse body of closure expression and return ClosureExpr.
-
private Int? closureCount
-
private ClosureExpr[] closures
-
private Expr collectionLiteralExpr(Location loc, CType? explicitType)
Collection literal:
<list> := [<type>] "[" <listItems> "]" <listItems> := "," | (<expr> ("," <expr>)*) <map> := [<mapType>] "[" <mapItems> "]" <mapItems> := ":" | (<mapPair> ("," <mapPair>)*) <mapPair> := <expr> ":" <expr>
-
private Expr condAndExpr()
Conditional and expression:
<condAndExpr> := <equalityExpr> ("&&" <equalityExpr>)*
-
private Expr condOrExpr()
Conditional or expression:
<condOrExpr> := <condAndExpr> ("||" <condAndExpr>)*
-
private TokenVal consume(Token? kind := null)
Consume the current token and return consumed token. If kind is non-null then verify first
-
private Str consumeId()
Verify current is an identifier, consume it, and return it.
-
private ContinueStmt continueStmt()
Continue statement:
<continue> := "continue" <eos>
-
private CType ctype()
Type signature:
<type> := <simpleType> | <listType> | <mapType> | <funcType> <listType> := <type> "[]" <mapType> := ["["] <type> ":" <type> ["]"]
-
private TokenVal cur
-
private ClosureExpr curClosure
-
private SlotDef? curSlot
-
private TypeDef? curType
-
private Token curt
-
private Str[]? doc()
Parse fandoc or retur null
-
private Expr elvisExpr()
Elvis expression:
<elvisExpr> := <condOrExpr> "?:" <condOrExpr>
-
private Bool endOfStmt(Str? errMsg := ...)
Statements can be terminated with a semicolon, end of line or } end of block. Return true on success. On failure return false if errMsg is null or log/throw an exception.
-
private EnumDef enumDef(Int ordinal)
Enum definition:
<enumDef> := <id> ["(" <args> ")"]
-
private Void enumDefs(TypeDef def)
Enum definition list:
<enumDefs> := <enumDef> ("," <enumDef>)* <eos>
-
private Expr equalityExpr()
Equality expression:
<equalityExpr> := <relationalExpr> (("==" | "!=" | "===" | "!==") <relationalExpr>)*
- errSource
-
override CompilerErr err(Str msg, Location? loc := null)
Overrides compiler::CompilerSupport.err
Doc inherited from compiler::CompilerSupport.err
Create, log, and return a CompilerErr.
-
private Expr expr()
Expression:
<expr> := <assignExpr>
-
private Stmt exprOrLocalDefStmt(Bool isEndOfStmt)
Expression or local variable declaration:
<exprStmt> := <expr> <eos> <localDef> := [<type>] <id> [":=" <expr>] <eos>
-
private FieldDef fieldDef(Location loc, TypeDef parent, Str[]? doc, [Str:FacetDef]? facets, Int flags, TypeRef? type, Str name)
Field definition:
<fieldDef> := <facets> <fieldFlags> [<type>] <id> [":=" <expr>] [ "{" [<fieldGetter>] [<fieldSetter>] "}" ] <eos> <fieldFlags> := [<protection>] ["readonly"] ["static"] <fieldGetter> := "get" (<eos> | <block>) <fieldSetter> := <protection> "set" (<eos> | <block>)
-
private Int flags(Bool normalize := true)
Parse any list of flags in any order, we will check invalid combinations in the CheckErrors step.
-
private ForStmt forStmt()
For statement:
<for> := "for" "(" [<forInit>] ";" <expr> ";" <expr> ")" <block> <forInit> := <expr> | <localDef>
-
private CType funcType()
Method type signature:
<funcType> := "|" <formals> ["->" <type> "|" <formals> := [<formal> ("," <formal>)*] <formal> := <type> <id>
-
private Expr idExpr(Expr? target, Bool dynamicCall, Bool safeCall)
Identifier expression:
<idExpr> := <local> | <field> | <call> <local> := <id> <field> := ["@"] <id>
-
private IfStmt ifStmt()
If/else statement:
<if> := "if" "(" <expr> ")" <block> [ "else" <block> ]
-
private Bool inFieldInit := false
-
private Bool inVoid
-
private Expr indexExpr(Expr target)
Index expression:
<indexExpr> := "[" <expr> "]"
-
private Bool isSys := false
-
private ListLiteralExpr listLiteralExpr(Location loc, CType? explicitType, Expr? first)
Parse List literal; if first is null then
cur must be on lbracket
else
cur must be on comma after first item
-
private LocalDefStmt localDefStmt(Location loc, CType? localType, Bool isEndOfStmt)
Parse local variable declaration, the current token must be the identifier of the local variable.
- makeSource
-
new make(Compiler compiler, CompilationUnit unit, ClosureExpr[] closures)
Construct the parser for the specified compilation unit.
-
private MapLiteralExpr mapLiteralExpr(Location loc, CType? explicitType, Expr? first)
Parse Map literal; if first is null:
cur must be on lbracket
else
cur must be on colon of first key/value pair
-
private MethodDef methodDef(Location loc, TypeDef parent, Str[]? doc, [Str:FacetDef]? facets, Int flags, TypeRef ret, Str name)
Method definition:
<methodDef> := <facets> <methodFlags> <type> <id> "(" <params> ")" <methodBody> <methodFlags> := [<protection>] ["virtual"] ["override"] ["abstract"] ["static"] <params> := [<param> ("," <param>)*] <param> := <type> <id> [":=" <expr>] <methodBody> := <eos> | ( "{" <stmts> "}" )
-
private Expr multiplicativeExpr()
Multiplicative expression:
<multExpr> := <parenExpr> (("*" | "/" | "%") <parenExpr>)*
-
private Int numTokens
-
private ParamDef paramDef()
-
private Expr parenExpr()
Paren grouped expression:
<parenExpr> := <unaryExpr> | <castExpr> | <groupedExpr> <castExpr> := "(" <type> ")" <parenExpr> <groupedExpr> := "(" <expr> ")" <termChain>*
- parseSource
-
Void parse()
Top level parse a compilation unit:
<compilationUnit> := [<usings>] <typeDef>*
-
private TokenVal peek
-
private Token peekt
-
private Int pos
-
private Expr rangeExpr()
Range expression:
<rangeExpr> := <bitOrExpr> ((".." | "...") <bitOrExpr>)*
-
private Expr relationalExpr()
Relational expression:
<relationalExpr> := <rangeExpr> (("is" | "as" | "<" | "<=" | ">" | ">=" | "<=>") <rangeExpr>)*
-
Reset the current position to the specified tokens index.
-
private ReturnStmt returnStmt()
Return statement:
<return> := "return" [<expr>] <eos>
-
private Expr shiftExpr()
Bitwise shift expression:
<shiftExpr> := <addExpr> (("<<" | ">>") <addExpr>)*
-
private CType simpleType()
Simple type signature:
<simpleType> := <id> ["::" <id>]
-
private SlotDef slotDef(TypeDef parent, Str[]? doc)
Slot definition:
<slotDef> := <fieldDef> | <methodDef> | <ctorDef>
-
private Stmt stmt()
Statement:
<stmt> := <break> | <continue> | <for> | <if> | <return> | <switch> | <throw> | <while> | <try> | <exprStmt> | <localDef>
-
private Block stmtOrBlock()
<block> := <stmt> | ( "{" <stmts> "}" ) <stmts> := <stmt>*
-
private Block switchBlock()
-
private SwitchStmt switchStmt()
Switch statement:
<switch> := "switch" "(" <expr> ")" "{" <case>* [<default>] "}" <case> := "case" <expr> ":" <stmts> <default> := "default" ":" <stmts>
-
private Expr termBaseExpr()
Atomic base of a termExpr
<termBase> := <literal> | <idExpr> | <closure> <literal> := "null" | "this" | "super" | <bool> | <int> | <float> | <str> | <duration> | <list> | <map> | <uri>
-
private Expr? termChainExpr(Expr target)
A chain expression is a piece of a term expression that may be chained together such as "call.var[x]". If the specified target expression contains a chained access, then return the new expression, otherwise return null.
<termChain> := <compiledCall> | <dynamicCall> | <indexExpr> | <withBlock> <compiledCall> := "." <idExpr> <dynamicCall> := "->" <idExpr>
-
private Expr termExpr(Expr? target := null)
A term is a base terminal such as a variable, call, or literal, optionally followed by a chain of accessor expressions - such as "x.y[z](a, b)".
<termExpr> := <termBase> <termChain>*
-
private Expr ternary()
Ternary expression:
<ternaryExpr> := <elvisExpr> "?" <elvisExpr> ":" <elvisExpr>
-
private ThrowStmt throwStmt()
Throw statement:
<throw> := "throw" <expr> <eos>
-
private TokenVal[] tokens
-
private Catch tryCatch()
-
private ClosureExpr? tryClosure()
Attempt to parse a closure expression or return null if we aren't positioned at the start of a closure expression.
-
private TryStmt tryStmt()
Try-catch-finally statement:
<try> := "try" "{" <stmt>* "}" <catch>* [<finally>] <catch> := "catch" [<catchDef>] "{" <stmt>* "}" <catchDef> := "(" <type> <id> ")" <finally> := "finally" "{" <stmt>* "}"
-
private CType? tryType()
If the current stream of tokens can be parsed as a valid type production return it. Otherwise leave the parser positioned on the current token.
-
private Expr typeBaseExpr(Location loc, CType ctype)
Handle a term expression which begins with a type literal.
- typeDefSource
-
Void typeDef()
TypeDef:
<typeDef> := <classDef> | <mixinDef> | <enumDef> <classDef> := <classHeader> <classBody> <classHeader> := [<doc>] <facets> <typeFlags> "class" [<inheritance>] <classFlags> := [<protection>] ["abstract"] ["final"] <classBody> := "{" <slotDefs> "}" <enumDef> := <enumHeader> <enumBody> <enumHeader> := [<doc>] <facets> <protection> "enum" [<inheritance>] <enumBody> := "{" <enumDefs> <slotDefs> "}" <mixinDef> := <enumHeader> <enumBody> <mixinHeader> := [<doc>] <facets> <protection> "mixin" [<inheritance>] <mixinBody> := "{" <slotDefs> "}" <protection> := "public" | "protected" | "private" | "internal" <inheritance> := ":" <typeList>
-
private TypeRef typeRef()
Parse a type production into a CType and wrap it as AST TypeRef.
-
private Expr unaryExpr()
Unary expression:
<unaryExpr> := <prefixExpr> | <termExpr> | <postfixExpr> <prefixExpr> := ("!" | "+" | "-" | "~" | "++" | "--") <parenExpr> <postfixExpr> := <termExpr> ("++" | "--")
-
private CompilationUnit unit
-
private Void usings()
Parse <using>* - note that we are just skipping them because they are already parsed by ScanForUsingsAndTypes.
<using> := <usingPod> | <usingType> | <usingAs> <usingPod> := "using" <id> <eos> <usingType> := "using" <id> "::" <id> <eos> <usingAs> := "using" <id> "::" <id> "as" <id> <eos>
-
private Void verify(Token kind)
Check that the current token matches the specified type, but do not consume it.
-
private WhileStmt whileStmt()
While statement:
<while> := "while" "(" <expr> ")" <block>
-
private Expr? withBlock(Expr base)
A with block is a series of sub-expressions inside {} appended to the end of an expression.
-
private Expr withSub(WithBaseExpr withBase)
Parse a with-block sub-expression. If we have a named expression, then it is implied to be against the withBase. Otherwise we assume syntax sugar for
withBase.add(sub)
. In case we get it wrong here, we try again in CallResolver.