paul@443 | 1 | # Grammar for Lichen |
paul@443 | 2 | |
paul@443 | 3 | # Start symbols for the grammar: |
paul@443 | 4 | # single_input is a single interactive statement; |
paul@443 | 5 | # file_input is a module or sequence of commands read from an input file; |
paul@443 | 6 | # eval_input is the input for the eval() and input() functions. |
paul@443 | 7 | # NB: compound_stmt in single_input is followed by extra NEWLINE! |
paul@443 | 8 | single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE |
paul@443 | 9 | file_input: (NEWLINE | stmt)* ENDMARKER |
paul@443 | 10 | eval_input: testlist NEWLINE* ENDMARKER |
paul@443 | 11 | |
paul@443 | 12 | funcdef: 'def' NAME parameters ':' suite |
paul@443 | 13 | parameters: '(' [varargslist] ')' |
paul@819 | 14 | # NOTE: Remove * and ** support. |
paul@443 | 15 | varargslist: ((fpdef ['=' test] ',')* |
paul@443 | 16 | ('*' NAME [',' '**' NAME] | '**' NAME) | |
paul@443 | 17 | fpdef ['=' test] (',' fpdef ['=' test])* [',']) |
paul@819 | 18 | # NOTE: Replace with flat parameter lists? |
paul@819 | 19 | # Supporting .name for attribute assignment convenience. |
paul@819 | 20 | fpdef: NAME | '.' NAME | '(' fplist ')' |
paul@443 | 21 | fplist: fpdef (',' fpdef)* [','] |
paul@443 | 22 | |
paul@443 | 23 | stmt: simple_stmt | compound_stmt |
paul@443 | 24 | simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE |
paul@443 | 25 | small_stmt: (expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | |
paul@443 | 26 | import_stmt | global_stmt | exec_stmt | assert_stmt) |
paul@443 | 27 | expr_stmt: testlist (augassign testlist | |
paul@443 | 28 | ('=' testlist)*) |
paul@443 | 29 | augassign: ('+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | |
paul@443 | 30 | '<<=' | '>>=' | '**=' | '//=') |
paul@443 | 31 | # For normal assignments, additional restrictions enforced by the interpreter |
paul@443 | 32 | print_stmt: 'print' ( [ test (',' test)* [','] ] | |
paul@443 | 33 | '>>' test [ (',' test)+ [','] ] ) |
paul@443 | 34 | del_stmt: 'del' exprlist |
paul@443 | 35 | pass_stmt: 'pass' |
paul@443 | 36 | flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt |
paul@443 | 37 | break_stmt: 'break' |
paul@443 | 38 | continue_stmt: 'continue' |
paul@443 | 39 | return_stmt: 'return' [testlist] |
paul@443 | 40 | raise_stmt: 'raise' [test [',' test [',' test]]] |
paul@443 | 41 | import_stmt: import_name | import_from |
paul@443 | 42 | import_name: 'import' dotted_as_names |
paul@506 | 43 | import_from: ('from' dotted_name |
paul@443 | 44 | 'import' ('*' | '(' import_as_names ')' | import_as_names)) |
paul@443 | 45 | import_as_name: NAME ['as' NAME] |
paul@443 | 46 | dotted_as_name: dotted_name ['as' NAME] |
paul@443 | 47 | import_as_names: import_as_name (',' import_as_name)* [','] |
paul@443 | 48 | dotted_as_names: dotted_as_name (',' dotted_as_name)* |
paul@443 | 49 | dotted_name: NAME ('.' NAME)* |
paul@443 | 50 | global_stmt: 'global' NAME (',' NAME)* |
paul@443 | 51 | exec_stmt: 'exec' expr ['in' test [',' test]] |
paul@443 | 52 | assert_stmt: 'assert' test [',' test] |
paul@443 | 53 | |
paul@621 | 54 | compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef |
paul@443 | 55 | if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] |
paul@443 | 56 | while_stmt: 'while' test ':' suite ['else' ':' suite] |
paul@443 | 57 | for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite] |
paul@443 | 58 | try_stmt: ('try' ':' suite |
paul@443 | 59 | ((except_clause ':' suite)+ |
paul@443 | 60 | ['else' ':' suite] |
paul@443 | 61 | ['finally' ':' suite] | |
paul@443 | 62 | 'finally' ':' suite)) |
paul@443 | 63 | # NB compile.c makes sure that the default except clause is last |
paul@443 | 64 | except_clause: 'except' [test [('as' | ',') test]] |
paul@443 | 65 | suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT |
paul@443 | 66 | |
paul@443 | 67 | # Backward compatibility cruft to support: |
paul@443 | 68 | # [ x for x in lambda: True, lambda: False if x() ] |
paul@443 | 69 | # even while also allowing: |
paul@443 | 70 | # lambda x: 5 if x else 2 |
paul@443 | 71 | # (But not a mix of the two) |
paul@443 | 72 | testlist_safe: old_test [(',' old_test)+ [',']] |
paul@443 | 73 | old_test: or_test | old_lambdef |
paul@443 | 74 | old_lambdef: 'lambda' [varargslist] ':' old_test |
paul@443 | 75 | |
paul@446 | 76 | test: or_test | lambdef |
paul@443 | 77 | or_test: and_test ('or' and_test)* |
paul@443 | 78 | and_test: not_test ('and' not_test)* |
paul@443 | 79 | not_test: 'not' not_test | comparison |
paul@443 | 80 | comparison: expr (comp_op expr)* |
paul@443 | 81 | comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not' |
paul@443 | 82 | expr: xor_expr ('|' xor_expr)* |
paul@443 | 83 | xor_expr: and_expr ('^' and_expr)* |
paul@443 | 84 | and_expr: shift_expr ('&' shift_expr)* |
paul@443 | 85 | shift_expr: arith_expr (('<<'|'>>') arith_expr)* |
paul@443 | 86 | arith_expr: term (('+'|'-') term)* |
paul@443 | 87 | term: factor (('*'|'/'|'%'|'//') factor)* |
paul@443 | 88 | factor: ('+'|'-'|'~') factor | power |
paul@443 | 89 | power: atom trailer* ['**' factor] |
paul@443 | 90 | atom: ('(' [testlist_comp] ')' | |
paul@443 | 91 | '[' [listmaker] ']' | |
paul@443 | 92 | '{' [dictorsetmaker] '}' | |
paul@443 | 93 | '`' testlist1 '`' | |
paul@443 | 94 | NAME | NUMBER | STRING+) |
paul@443 | 95 | listmaker: test ( (',' test)* [','] ) |
paul@443 | 96 | testlist_comp: test ( (',' test)* [','] ) |
paul@443 | 97 | lambdef: 'lambda' [varargslist] ':' test |
paul@443 | 98 | trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME |
paul@443 | 99 | subscriptlist: subscript (',' subscript)* [','] |
paul@443 | 100 | subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop] |
paul@443 | 101 | sliceop: ':' [test] |
paul@443 | 102 | exprlist: expr (',' expr)* [','] |
paul@443 | 103 | testlist: test (',' test)* [','] |
paul@443 | 104 | dictmaker: test ':' test (',' test ':' test)* [','] |
paul@443 | 105 | dictorsetmaker: ( (test ':' test ( (',' test ':' test)* [','])) | |
paul@443 | 106 | (test ( (',' test)* [','])) ) |
paul@443 | 107 | |
paul@443 | 108 | classdef: 'class' NAME ['(' [testlist] ')'] ':' suite |
paul@443 | 109 | |
paul@443 | 110 | arglist: (argument ',')* (argument [','] |
paul@443 | 111 | |'*' test (',' argument)* [',' '**' test] |
paul@443 | 112 | |'**' test) |
paul@443 | 113 | # The reason that keywords are test nodes instead of NAME is that using NAME |
paul@443 | 114 | # results in an ambiguity. ast.c makes sure it's a NAME. |
paul@443 | 115 | argument: test | test '=' test |
paul@443 | 116 | |
paul@443 | 117 | testlist1: test (',' test)* |
paul@443 | 118 | |
paul@443 | 119 | # not used in grammar, but may appear in "node" passed from Parser to Compiler |
paul@443 | 120 | encoding_decl: NAME |