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