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
-
const static Int Once := 2147483648
- ParserFlagsMaskSource
-
const static Int ParserFlagsMask := Readonly
- ProtectionMaskSource
-
const static Int ProtectionMask := ...
- ReadonlySource
-
const static Int Readonly := 1073741824
-
private Expr addExpr()
Additive expression:
<addExpr> := <multExpr> (("+" | "-") <multExpr>)*
-
private Expr assignExpr(Expr? expr := null)
Assignment expression:
<assignExpr> := <ifExpr> [<assignOp> <assignExpr>] <assignOp> := "=" | "*=" | "/=" | "%=" | "+=" | "-="
-
private Block block()
Top level for blocks which must be surrounded by braces
-
private BreakStmt breakStmt()
Break statement:
<break> := "break" <eos>
-
private Void callArgs(CallExpr call, Bool closureOk := true)
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(Loc loc, FuncType funcType)
Parse body of closure expression and return ClosureExpr.
-
private Int? closureCount
-
private ClosureExpr[] closures
-
private Expr collectionLiteralExpr(Loc loc, CType? explicitType)
Collection literal:
<list> := [<type>] "[" <listItems> "]" <listItems> := "," | (<expr> ("," <expr>)*) <map> := [<mapType>] "[" <mapItems> "]" <mapItems> := ":" | (<mapPair> ("," <mapPair>)*) <mapPair> := <expr> ":" <expr>
-
private Expr complexLiteral(Loc loc, CType ctype)
This is used to parse an it-block outside of the scope of a field or method definition. It is used to parse complex literals declared in a facet without mucking up the closure code path.
-
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 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, Loc? 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> <itAdd> := <expr> ("," <expr>)*
-
private FacetDef[]? facets()
Facet definition:
<facets> := <facet>* <facet> := "@" <simpleType> [<facetVals>] <facetVals> := "{" <facetVal> (<eos> <facetVal>)* "}" <facetVal> := <id> "=" <expr>
-
private FieldDef fieldDef(Loc loc, TypeDef parent, Str[]? doc, 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> := "|" ("->" | <funcTypeSig>) "|" <funcTypeSig> := <formals> ["->" <type>] <formals> := [<formal> ("," <formal>)*] <formal> := <formFull> | <formalInferred> | <formalTypeOnly> <formalFull> := <type> <id> <formalInferred> := <id> <formalTypeOnly> := <type>
-
private Expr idExpr(Expr? target, Bool dynamicCall, Bool safeCall)
Identifier expression:
<idExpr> := <local> | <field> | <call> <local> := <id> <field> := ["*"] <id>
-
private Expr ifExpr()
Ternary/Elvis expressions:
<ifExpr> := <ternaryExpr> | <elvisExpr> <ternaryExpr> := <condOrExpr> ["?" <ifExprBody> ":" <ifExprBody>] <elvisExpr> := <condOrExpr> "?:" <ifExprBody>
-
private Expr ifExprBody()
If expression body (ternary/elvis):
<ifExprBody> := <condOrExpr> | <ifExprThrow> <ifExprThrow> := "throw" <expr>
-
private IfStmt ifStmt()
If/else statement:
<if> := "if" "(" <expr> ")" <block> [ "else" <block> ]
-
private Bool inFieldInit
-
private Expr indexExpr(Expr target)
Index expression:
<indexExpr> := "[" <expr> "]"
-
private CType inheritType()
-
Comma operator is sugar for it.add(target):
<itAdd> := <expr> ("," <expr>)* <eos>
-
private ListLiteralExpr listLiteralExpr(Loc 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(Loc 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(Loc 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(Loc loc, TypeDef parent, Str[]? doc, 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 multExpr()
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> := <typeCheckExpr> | <compareExpr> <typeCheckExpr> := <rangeExpr> [("is" | "as" | "isnot") <type>] <compareExpr> := <rangeExpr> [("<" | "<=" | ">" | ">=" | "<=>") <rangeExpr>]
-
Reset the current position to the specified tokens index.
-
private ReturnStmt returnStmt()
Return statement:
<return> := "return" [<expr>] <eos>
-
private CType simpleType()
Simple type signature:
<simpleType> := <id> ["::" <id>]
-
private Void skipUsing()
-
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> | <itAdd>
-
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> | <dsl> <literal> := "null" | "this" | "super" | <bool> | <int> | <float> | <str> | <duration> | <list> | <map> | <uri> | <typeLiteral> | <slotLiteral> <typeLiteral> := <type> "#" <slotLiteral> := [<type>] "#" <id>
-
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> <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 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 ClosureExpr? tryItBlock()
Parse it-block closure.
-
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(Loc loc, CType ctype)
Handle a term expression which begins with a type literal.
- typeDefSource
-
Void typeDef()
TypeDef:
<typeDef> := <classDef> | <mixinDef> | <enumDef> | <facetDef> <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> "}" <facetDef := <facetHeader> <enumBody> <facetHeader> := [<doc>] <facets> [<protection>] "facet" "class" <id> [<inheritance>] <facetBody> := "{" <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" <podSpec> <eos> <usingType> := "using" <podSpec> "::" <id> <eos> <usingAs> := "using" <podSpec> "::" <id> "as" <id> <eos> <podSpec> := <id> | <str> | <ffiPodSpec> <ffiPodSpec> := "[" <id> "]" <id> ("." <id>)*
-
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>