|
| 1 | +%{ |
| 2 | + |
| 3 | +package parser |
| 4 | + |
| 5 | +// Grammar for Python |
| 6 | + |
| 7 | +import ( |
| 8 | + "github.com/ncw/gpython/py" |
| 9 | +) |
| 10 | + |
| 11 | +%} |
| 12 | + |
| 13 | +%union { |
| 14 | + str string |
| 15 | + obj py.Object |
| 16 | +} |
| 17 | + |
| 18 | +%token NEWLINE |
| 19 | +%token ENDMARKER |
| 20 | +%token <str> NAME |
| 21 | +%token INDENT |
| 22 | +%token DEDENT |
| 23 | +%token <str> STRING |
| 24 | +%token <str> NUMBER |
| 25 | + |
| 26 | +%token PLINGEQ // != |
| 27 | +%token PERCEQ // %= |
| 28 | +%token ANDEQ // &= |
| 29 | +%token STARSTAR // ** |
| 30 | +%token STARSTAREQ // **= |
| 31 | +%token STAREQ // *= |
| 32 | +%token PLUSEQ // += |
| 33 | +%token MINUSEQ // -= |
| 34 | +%token MINUSGT // -> |
| 35 | +%token ELIPSIS // ... |
| 36 | +%token DIVDIV // // |
| 37 | +%token DIVDIVEQ // //= |
| 38 | +%token DIVEQ // /= |
| 39 | +%token LTLT // << |
| 40 | +%token LTLTEQ // <<= |
| 41 | +%token LTEQ // <= |
| 42 | +%token LTGT // <> |
| 43 | +%token EQEQ // == |
| 44 | +%token GTEQ // >= |
| 45 | +%token GTGT // >> |
| 46 | +%token GTGTEQ // >>= |
| 47 | +%token HATEQ // ^= |
| 48 | +%token PIPEEQ // |= |
| 49 | + |
| 50 | +%token FALSE // False |
| 51 | +%token NONE // None |
| 52 | +%token TRUE // True |
| 53 | +%token AND // and |
| 54 | +%token AS // as |
| 55 | +%token ASSERT // assert |
| 56 | +%token BREAK // break |
| 57 | +%token CLASS // class |
| 58 | +%token CONTINUE // continue |
| 59 | +%token DEF // def |
| 60 | +%token DEL // del |
| 61 | +%token ELIF // elif |
| 62 | +%token ELSE // else |
| 63 | +%token EXCEPT // except |
| 64 | +%token FINALLY // finally |
| 65 | +%token FOR // for |
| 66 | +%token FROM // from |
| 67 | +%token GLOBAL // global |
| 68 | +%token IF // if |
| 69 | +%token IMPORT // import |
| 70 | +%token IN // in |
| 71 | +%token IS // is |
| 72 | +%token LAMBDA // lambda |
| 73 | +%token
8000
NONLOCAL // nonlocal |
| 74 | +%token NOT // not |
| 75 | +%token OR // or |
| 76 | +%token PASS // pass |
| 77 | +%token RAISE // raise |
| 78 | +%token RETURN // return |
| 79 | +%token TRY // try |
| 80 | +%token WHILE // while |
| 81 | +%token WITH // with |
| 82 | +%token YIELD // yield |
| 83 | + |
| 84 | +%token '(' ')' '[' ']' ':' ',' ';' '+' '-' '*' '/' '|' '&' '<' '>' '=' '.' '%' '{' '}' '^' '~' '@' |
| 85 | + |
| 86 | +// Note: Changing the grammar specified in this file will most likely |
| 87 | +// require corresponding changes in the parser module |
| 88 | +// (../Modules/parsermodule.c). If you can't make the changes to |
| 89 | +// that module yourself, please co-ordinate the required changes |
| 90 | +// with someone who can; ask around on python-dev for help. Fred |
| 91 | +// Drake <fdrake@acm.org> will probably be listening there. |
| 92 | + |
| 93 | +// NOTE WELL: You should also follow all the steps listed in PEP 306, |
| 94 | +// "How to Change Python's Grammar" |
| 95 | + |
| 96 | +// Start symbols for the grammar: |
| 97 | +// single_input is a single interactive statement; |
| 98 | +// file_input is a module or sequence of commands read from an input file; |
| 99 | +// eval_input is the input for the eval() functions. |
| 100 | +// NB: compound_stmt in single_input is followed by extra NEWLINE! |
| 101 | + |
| 102 | +%% |
| 103 | + |
| 104 | +// FIXME figure out how to tell the parser to start from a given node |
| 105 | +// inputs: single_input | file_input | eval_input |
| 106 | +// In the mean time just do file_input |
| 107 | +// inputs: single_input | file_input | eval_input |
| 108 | +inputs: file_input |
| 109 | + |
| 110 | +single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE |
| 111 | + |
| 112 | +// (NEWLINE | stmt)* |
| 113 | +nl_or_stmt: | nl_or_stmt NEWLINE | nl_or_stmt stmt |
| 114 | + |
| 115 | +//file_input: (NEWLINE | stmt)* ENDMARKER |
| 116 | +file_input: nl_or_stmt ENDMARKER |
| 117 | + |
| 118 | +// NEWLINE* |
| 119 | +nls: | nls NEWLINE |
| 120 | + |
| 121 | +//eval_input: testlist NEWLINE* ENDMARKER |
| 122 | +eval_input: testlist nls ENDMARKER |
| 123 | + |
| 124 | +optional_arglist: | arglist |
| 125 | +optional_arglist_call: | '(' optional_arglist ')' |
| 126 | +decorator: '@' dotted_name optional_arglist_call NEWLINE |
| 127 | +decorators: decorator | decorators decorator |
| 128 | +classdef_or_funcdef: classdef | funcdef |
| 129 | +decorated: decorators classdef_or_funcdef |
| 130 | +optional_return_type: | MINUSGT test |
| 131 | +funcdef: DEF NAME parameters optional_return_type ':' suite |
| 132 | +parameters: '(' optional_typedargslist ')' |
| 133 | +optional_typedargslist: | typedargslist |
| 134 | +// (',' tfpdef ['=' test])* |
| 135 | +tfpdeftest: tfpdef | tfpdef '=' test |
| 136 | +tfpdeftests: | tfpdeftests ',' tfpdeftest |
| 137 | +optional_tfpdef: | tfpdef |
| 138 | + |
| 139 | +typedargslist: |
| 140 | + tfpdeftest tfpdeftests |
| 141 | + | tfpdeftest tfpdeftests ',' |
| 142 | + | tfpdeftest tfpdeftests ',' '*' optional_tfpdef tfpdeftests |
| 143 | + | tfpdeftest tfpdeftests ',' '*' optional_tfpdef tfpdeftests ',' STARSTAR tfpdef |
| 144 | + | tfpdeftest tfpdeftests ',' STARSTAR tfpdef |
| 145 | + | '*' optional_tfpdef tfpdeftests |
| 146 | + | '*' optional_tfpdef tfpdeftests ',' STARSTAR tfpdef |
| 147 | + | STARSTAR tfpdef |
| 148 | + |
| 149 | +tfpdef: NAME |
| 150 | + | NAME ':' test |
| 151 | + |
| 152 | +vfpdeftest: vfpdef | vfpdef '=' test |
| 153 | +vfpdeftests: | vfpdeftests ',' vfpdeftest |
| 154 | +optional_vfpdef: | vfpdef |
| 155 | +varargslist: vfpdeftest vfpdeftests |
| 156 | + | vfpdeftest vfpdeftests ',' |
| 157 | + | vfpdeftest vfpdeftests ',' '*' optional_vfpdef vfpdeftests |
| 158 | + | vfpdeftest vfpdeftests ',' '*' optional_vfpdef vfpdeftests ',' STARSTAR vfpdef |
| 159 | + | vfpdeftest vfpdeftests ',' STARSTAR vfpdef |
| 160 | + | '*' optional_vfpdef vfpdeftests |
| 161 | + | '*' optional_vfpdef vfpdeftests ','
8000
; STARSTAR vfpdef |
| 162 | + | STARSTAR vfpdef |
| 163 | + |
| 164 | +vfpdef: NAME |
| 165 | + |
| 166 | +stmt: simple_stmt | compound_stmt |
| 167 | +optional_semicolon: | ';' |
| 168 | +small_stmts: small_stmt | small_stmts ';' small_stmt |
| 169 | +simple_stmt: small_stmts optional_semicolon NEWLINE |
| 170 | +small_stmt: expr_stmt | del_stmt | pass_stmt | flow_stmt | |
| 171 | + import_stmt | global_stmt | nonlocal_stmt | assert_stmt |
| 172 | +yield_expr_or_testlist: yield_expr|testlist |
| 173 | +yield_expr_or_testlist_star_expr: yield_expr|testlist_star_expr |
| 174 | +equals_yield_expr_or_testlist_star_expr: | equals_yield_expr_or_testlist_star_expr '=' yield_expr_or_testlist_star_expr |
| 175 | +expr_stmt: testlist_star_expr augassign yield_expr_or_testlist | |
| 176 | + testlist_star_expr equals_yield_expr_or_testlist_star_expr |
| 177 | +// FIXME this is making a reduce/reduce error for some reason :-( |
| 178 | +test_or_star_expr: test | star_expr |
| 179 | +test_or_star_exprs: test_or_star_expr | test_or_star_exprs ',' test_or_star_expr |
| 180 | +optional_comma: | ',' |
| 181 | +testlist_star_expr: test_or_star_exprs optional_comma |
| 182 | +augassign: PLUSEQ | MINUSEQ | STAREQ | DIVEQ | PERCEQ | ANDEQ | PIPEEQ | HATEQ | |
| 183 | + LTLTEQ | GTGTEQ | STARSTAREQ | DIVDIVEQ |
| 184 | +// For normal assignments, additional restrictions enforced by the interpreter |
| 185 | +del_stmt: DEL exprlist |
| 186 | +pass_stmt: PASS |
| 187 | +flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt |
| 188 | +break_stmt: BREAK |
| 189 | +continue_stmt: CONTINUE |
| 190 | +return_stmt: RETURN | RETURN testlist |
| 191 | +yield_stmt: yield_expr |
| 192 | +raise_stmt: RAISE | RAISE test | RAISE test FROM test |
| 193 | +import_stmt: import_name | import_from |
| 194 | +import_name: IMPORT dotted_as_names |
| 195 | +// note below: the ('.' | '...') is necessary because '...' is tokenized as ELLIPSIS |
| 196 | +import_dots: | import_dots '.' | import_dots ELIPSIS |
| 197 | +import_dots_plus: '.' | ELIPSIS | import_dots |
| 198 | +from_arg: import_dots dotted_name | import_dots_plus |
| 199 | +import_from_arg: '*' | '(' import_as_names ')' | import_as_names |
| 200 | +import_from: FROM from_arg IMPORT import_from_arg |
| 201 | +import_as_name: NAME | NAME AS NAME |
| 202 | +dotted_as_name: dotted_name | dotted_name AS NAME |
| 203 | +import_as_names: import_as_name optional_comma | import_as_name ',' import_as_names |
| 204 | +dotted_as_names: dotted_as_name | dotted_as_names ',' dotted_as_name |
| 205 | +dotted_name: NAME | dotted_name '.' NAME |
| 206 | +names: NAME | names ',' NAME |
| 207 | +global_stmt: GLOBAL names |
| 208 | +nonlocal_stmt: NONLOCAL names |
| 209 | +tests: test | tests ',' test |
| 210 | +assert_stmt: ASSERT tests |
| 211 | + |
| 212 | +compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated |
| 213 | +elifs: | elifs ELIF test ':' suite |
| 214 | +optional_else: | ELSE ':' suite |
| 215 | +if_stmt: IF test ':' suite elifs optional_else |
| 216 | +while_stmt: WHILE test ':' suite optional_else |
| 217 | +for_stmt: FOR exprlist IN testlist ':' suite optional_else |
| 218 | +except_clauses: | except_clauses except_clause ':' suite |
| 219 | +try_stmt: TRY ':' suite except_clauses optional_else |
| 220 | + | TRY ':' suite except_clauses optional_else FINALLY ':' suite |
| 221 | + | TRY ':' suite FINALLY ':' suite |
| 222 | +with_items: with_item | with_items ',' with_item |
| 223 | +with_stmt: WITH with_items ':' suite |
| 224 | +with_item: test | test AS expr |
| 225 | +// NB compile.c makes sure that the default except clause is last |
| 226 | +except_clause: EXCEPT | EXCEPT test | EXCEPT test AS NAME |
| 227 | +stmts: stmt | stmts stmt |
| 228 | +suite: simple_stmt | NEWLINE INDENT stmts DEDENT |
| 229 | + |
| 230 | +test: or_test | or_test IF or_test ELSE test | lambdef |
| 231 | +test_nocond: or_test | lambdef_nocond |
| 232 | +lambdef: LAMBDA ':' test | LAMBDA varargslist ':' test |
| 233 | +lambdef_nocond: LAMBDA ':' test_nocond | LAMBDA varargslist ':' test_nocond |
| 234 | +or_test: and_test | or_test OR and_test |
| 235 | +and_test: not_test | and_test AND not_test |
| 236 | +not_test: NOT not_test | comparison |
| 237 | +comparison: expr | comparison comp_op expr |
| 238 | +// <> LTGT isn't actually a valid comparison operator in Python. It's here for the |
| 239 | +// sake of a __future__ import described in PEP 401 |
| 240 | +comp_op: '<'|'>'|EQEQ|GTEQ|LTEQ|LTGT|PLINGEQ|IN|NOT IN|IS|IS NOT |
| 241 | +star_expr: '*' expr |
| 242 | +expr: xor_expr | expr '|' xor_expr |
| 243 | +xor_expr: and_expr | xor_expr '^' and_expr |
| 244 | +and_expr: shift_expr | and_expr '&' shift_expr |
| 245 | +shift_expr: arith_expr | shift_expr LTLT arith_expr| shift_expr GTGT arith_expr |
| 246 | +arith_expr: term | arith_expr '+' term | arith_expr '-' term |
| 247 | +term: factor | term '*' factor| term '/' factor| term '%' factor| term DIVDIV factor |
| 248 | +factor: '+' factor | '-' factor | '~' factor | power |
| 249 | +trailers: | trailers trailer |
| 250 | +power: atom trailers | atom trailers STARSTAR factor |
| 251 | +strings: STRING | strings STRING |
| 252 | +atom: '(' ')' | |
| 253 | + '(' yield_expr ')' | |
| 254 | + '(' testlist_comp ')' | |
| 255 | + '[' ']' | |
| 256 | + '[' testlist_comp ']' | |
| 257 | + '{' '}' | |
| 258 | + '{' dictorsetmaker '}' | |
| 259 | + NAME | NUMBER | strings | ELIPSIS | NONE | TRUE | FALSE |
| 260 | +testlist_comp: test_or_star_expr comp_for | test_or_star_expr test_or_star_exprs optional_comma |
| 261 | +trailer: '(' ')' | '(' arglist ')' | '[' subscriptlist ']' | '.' NAME |
| 262 | +subscripts: subscript | subscripts ',' subscript |
| 263 | +subscriptlist: subscripts optional_comma |
| 264 | +subscript: test |
| 265 | +| ':' |
| 266 | +| ':' sliceop |
| 267 | +| ':' test |
| 268 | +| ':' test sliceop |
| 269 | +| test ':' |
| 270 | +| test ':' sliceop |
| 271 | +| test ':' test |
| 272 | +| test ':' test sliceop |
| 273 | +sliceop: ':' | ':' test |
| 274 | +expr_or_star_expr: expr|star_expr |
| 275 | +expr_or_star_exprs: expr_or_star_expr | expr_or_star_exprs ',' expr_or_star_expr |
| 276 | +exprlist: expr_or_star_exprs optional_comma |
| 277 | +testlist: tests optional_comma |
| 278 | +// (',' test ':' test)* |
| 279 | +test_colon_tests: test ':' test | test_colon_tests ',' test ':' test |
| 280 | +dictorsetmaker: test_colon_tests optional_comma |
| 281 | + | test ':' test comp_for |
| 282 | + | test testlist |
| 283 | + | test comp_for |
| 284 | + |
| 285 | +classdef: CLASS NAME optional_arglist_call ':' suite |
| 286 | + |
| 287 | +comma_arguments: | comma_arguments ',' argument |
| 288 | +arglist: comma_arguments argument optional_comma |
| 289 | + | comma_arguments '*' test comma_arguments |
| 290 | + | comma_arguments '*' test comma_arguments ',' STARSTAR test |
| 291 | + | comma_arguments STARSTAR test |
| 292 | +// The reason that keywords are test nodes instead of NAME is that using NAME |
| 293 | +// results in an ambiguity. ast.c makes sure it's a NAME. |
| 294 | +argument: test |
| 295 | + | test comp_for |
| 296 | + | test '=' test // Really [keyword '='] test |
| 297 | +comp_iter: comp_for | comp_if |
| 298 | +comp_for: FOR exprlist IN or_test |
| 299 | + | FOR exprlist IN or_test comp_iter |
| 300 | +comp_if: IF test_nocond |
| 301 | + | IF test_nocond comp_iter |
| 302 | +
|
| 303 | +// not used in grammar, but may appear in "node" passed from Parser to Compiler |
| 304 | +// encoding_decl: NAME |
| 305 | +
|
| 306 | +yield_expr: YIELD |
| 307 | + | YIELD yield_arg |
| 308 | +yield_arg: FROM test | testlist |
0 commit comments