1*4947cdc7SCole Faust 2*4947cdc7SCole FaustGrammar of Starlark 3*4947cdc7SCole Faust================== 4*4947cdc7SCole Faust 5*4947cdc7SCole FaustFile = {Statement | newline} eof . 6*4947cdc7SCole Faust 7*4947cdc7SCole FaustStatement = DefStmt | IfStmt | ForStmt | WhileStmt | SimpleStmt . 8*4947cdc7SCole Faust 9*4947cdc7SCole FaustDefStmt = 'def' identifier '(' [Parameters [',']] ')' ':' Suite . 10*4947cdc7SCole Faust 11*4947cdc7SCole FaustParameters = Parameter {',' Parameter}. 12*4947cdc7SCole Faust 13*4947cdc7SCole FaustParameter = identifier | identifier '=' Test | '*' | '*' identifier | '**' identifier . 14*4947cdc7SCole Faust 15*4947cdc7SCole FaustIfStmt = 'if' Test ':' Suite {'elif' Test ':' Suite} ['else' ':' Suite] . 16*4947cdc7SCole Faust 17*4947cdc7SCole FaustForStmt = 'for' LoopVariables 'in' Expression ':' Suite . 18*4947cdc7SCole Faust 19*4947cdc7SCole FaustWhileStmt = 'while' Test ':' Suite . 20*4947cdc7SCole Faust 21*4947cdc7SCole FaustSuite = [newline indent {Statement} outdent] | SimpleStmt . 22*4947cdc7SCole Faust 23*4947cdc7SCole FaustSimpleStmt = SmallStmt {';' SmallStmt} [';'] '\n' . 24*4947cdc7SCole Faust# NOTE: '\n' optional at EOF 25*4947cdc7SCole Faust 26*4947cdc7SCole FaustSmallStmt = ReturnStmt 27*4947cdc7SCole Faust | BreakStmt | ContinueStmt | PassStmt 28*4947cdc7SCole Faust | AssignStmt 29*4947cdc7SCole Faust | ExprStmt 30*4947cdc7SCole Faust | LoadStmt 31*4947cdc7SCole Faust . 32*4947cdc7SCole Faust 33*4947cdc7SCole FaustReturnStmt = 'return' [Expression] . 34*4947cdc7SCole FaustBreakStmt = 'break' . 35*4947cdc7SCole FaustContinueStmt = 'continue' . 36*4947cdc7SCole FaustPassStmt = 'pass' . 37*4947cdc7SCole FaustAssignStmt = Expression ('=' | '+=' | '-=' | '*=' | '/=' | '//=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>>=') Expression . 38*4947cdc7SCole FaustExprStmt = Expression . 39*4947cdc7SCole Faust 40*4947cdc7SCole FaustLoadStmt = 'load' '(' string {',' [identifier '='] string} [','] ')' . 41*4947cdc7SCole Faust 42*4947cdc7SCole FaustTest = LambdaExpr 43*4947cdc7SCole Faust | IfExpr 44*4947cdc7SCole Faust | PrimaryExpr 45*4947cdc7SCole Faust | UnaryExpr 46*4947cdc7SCole Faust | BinaryExpr 47*4947cdc7SCole Faust . 48*4947cdc7SCole Faust 49*4947cdc7SCole FaustLambdaExpr = 'lambda' [Parameters] ':' Test . 50*4947cdc7SCole Faust 51*4947cdc7SCole FaustIfExpr = Test 'if' Test 'else' Test . 52*4947cdc7SCole Faust 53*4947cdc7SCole FaustPrimaryExpr = Operand 54*4947cdc7SCole Faust | PrimaryExpr DotSuffix 55*4947cdc7SCole Faust | PrimaryExpr CallSuffix 56*4947cdc7SCole Faust | PrimaryExpr SliceSuffix 57*4947cdc7SCole Faust . 58*4947cdc7SCole Faust 59*4947cdc7SCole FaustOperand = identifier 60*4947cdc7SCole Faust | int | float | string 61*4947cdc7SCole Faust | ListExpr | ListComp 62*4947cdc7SCole Faust | DictExpr | DictComp 63*4947cdc7SCole Faust | '(' [Expression [',']] ')' 64*4947cdc7SCole Faust | ('-' | '+') PrimaryExpr 65*4947cdc7SCole Faust . 66*4947cdc7SCole Faust 67*4947cdc7SCole FaustDotSuffix = '.' identifier . 68*4947cdc7SCole FaustCallSuffix = '(' [Arguments [',']] ')' . 69*4947cdc7SCole FaustSliceSuffix = '[' [Expression] [':' Test [':' Test]] ']' . 70*4947cdc7SCole Faust 71*4947cdc7SCole FaustArguments = Argument {',' Argument} . 72*4947cdc7SCole FaustArgument = Test | identifier '=' Test | '*' Test | '**' Test . 73*4947cdc7SCole Faust 74*4947cdc7SCole FaustListExpr = '[' [Expression [',']] ']' . 75*4947cdc7SCole FaustListComp = '[' Test {CompClause} ']'. 76*4947cdc7SCole Faust 77*4947cdc7SCole FaustDictExpr = '{' [Entries [',']] '}' . 78*4947cdc7SCole FaustDictComp = '{' Entry {CompClause} '}' . 79*4947cdc7SCole FaustEntries = Entry {',' Entry} . 80*4947cdc7SCole FaustEntry = Test ':' Test . 81*4947cdc7SCole Faust 82*4947cdc7SCole FaustCompClause = 'for' LoopVariables 'in' Test | 'if' Test . 83*4947cdc7SCole Faust 84*4947cdc7SCole FaustUnaryExpr = 'not' Test . 85*4947cdc7SCole Faust 86*4947cdc7SCole FaustBinaryExpr = Test {Binop Test} . 87*4947cdc7SCole Faust 88*4947cdc7SCole FaustBinop = 'or' 89*4947cdc7SCole Faust | 'and' 90*4947cdc7SCole Faust | '==' | '!=' | '<' | '>' | '<=' | '>=' | 'in' | 'not' 'in' 91*4947cdc7SCole Faust | '|' 92*4947cdc7SCole Faust | '^' 93*4947cdc7SCole Faust | '&' 94*4947cdc7SCole Faust | '-' | '+' 95*4947cdc7SCole Faust | '*' | '%' | '/' | '//' 96*4947cdc7SCole Faust . 97*4947cdc7SCole Faust 98*4947cdc7SCole FaustExpression = Test {',' Test} . 99*4947cdc7SCole Faust# NOTE: trailing comma permitted only when within [...] or (...). 100*4947cdc7SCole Faust 101*4947cdc7SCole FaustLoopVariables = PrimaryExpr {',' PrimaryExpr} . 102*4947cdc7SCole Faust 103*4947cdc7SCole Faust 104*4947cdc7SCole Faust# Notation (similar to Go spec): 105*4947cdc7SCole Faust- lowercase and 'quoted' items are lexical tokens. 106*4947cdc7SCole Faust- Capitalized names denote grammar productions. 107*4947cdc7SCole Faust- (...) implies grouping 108*4947cdc7SCole Faust- x | y means either x or y. 109*4947cdc7SCole Faust- [x] means x is optional 110*4947cdc7SCole Faust- {x} means x is repeated zero or more times 111*4947cdc7SCole Faust- The end of each declaration is marked with a period. 112*4947cdc7SCole Faust 113*4947cdc7SCole Faust# Tokens 114*4947cdc7SCole Faust- spaces: newline, eof, indent, outdent. 115*4947cdc7SCole Faust- identifier. 116*4947cdc7SCole Faust- literals: string, int, float. 117*4947cdc7SCole Faust- plus all quoted tokens such as '+=', 'return'. 118*4947cdc7SCole Faust 119*4947cdc7SCole Faust# Notes: 120*4947cdc7SCole Faust- Ambiguity is resolved using operator precedence. 121*4947cdc7SCole Faust- The grammar does not enforce the legal order of params and args, 122*4947cdc7SCole Faust nor that the first compclause must be a 'for'. 123*4947cdc7SCole Faust 124*4947cdc7SCole FaustTODO: 125*4947cdc7SCole Faust- explain how the lexer generates indent, outdent, and newline tokens. 126*4947cdc7SCole Faust- why is unary NOT separated from unary - and +? 127*4947cdc7SCole Faust- the grammar is (mostly) in LL(1) style so, for example, 128*4947cdc7SCole Faust dot expressions are formed suffixes, not complete expressions, 129*4947cdc7SCole Faust which makes the spec harder to read. Reorganize into non-LL(1) form? 130