1/* Grammar from Python 2.2.2 Grammar/Grammar, converted to dparser */ 2 3{ 4#include "dparse_tables.h" 5typedef struct PythonGlobals { 6 int indent_stack[1024]; 7 int *current_indent; 8 int implicit_line_joining; 9} PythonGlobals; 10#define D_ParseNode_Globals PythonGlobals 11int python_indent(PythonGlobals **p_globals); 12int python_dedent(PythonGlobals **p_globals); 13void python_whitespace(struct D_Parser *p, d_loc_t *loc, void **p_globals); 14} 15 16${declare longest_match} 17${declare subparser single_input} 18${declare subparser eval_input} 19${declare whitespace python_whitespace} 20 21file_input: (NEWLINE | stmt)*; 22single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE; 23eval_input: testlist NEWLINE*; 24 25funcdef: 'def' NAME parameters ':' suite; 26parameters: LP varargslist? RP; 27varargslist: (fpdef ('=' test)? ',')* ('*' NAME (',' '**' NAME) | '**' NAME) | fpdef ('=' test)? (',' fpdef ('=' test)?)* ','?; 28fpdef: NAME | LP fplist RP; 29fplist: fpdef (',' fpdef)* ','?; 30 31stmt: simple_stmt | compound_stmt; 32simple_stmt: small_stmt (';' small_stmt)* ';'? NEWLINE; 33small_stmt: expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | exec_stmt | assert_stmt; 34expr_stmt: testlist (augassign testlist | ('=' testlist)*); 35augassign: '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>>=' | '**=' | '//='; 36/* For normal assignments, additional restrictions enforced by the interpreter */ 37print_stmt: 'print' ( ( test (',' test)* ','? )? | '>>' test ( (',' test)+ ','? )? ); 38del_stmt: 'del' exprlist; 39pass_stmt: 'pass'; 40flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt; 41break_stmt: 'break'; 42continue_stmt: 'continue'; 43return_stmt: 'return' testlist?; 44yield_stmt: 'yield' testlist; 45raise_stmt: 'raise' (test (',' test (',' test)?)?)?; 46import_stmt: 'import' dotted_as_name (',' dotted_as_name)* | 'from' dotted_name 'import' ('*' | import_as_name (',' import_as_name)*); 47import_as_name: NAME (NAME NAME)?; 48dotted_as_name: dotted_name (NAME NAME)?; 49dotted_name: NAME ('.' NAME)*; 50global_stmt: 'global' NAME (',' NAME)*; 51exec_stmt: 'exec' expr ('in' test (',' test)?)?; 52assert_stmt: 'assert' test (',' test)?; 53 54compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef; 55if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ('else' ':' suite)?; 56while_stmt: 'while' test ':' suite ('else' ':' suite)?; 57for_stmt: 'for' exprlist 'in' testlist ':' suite ('else' ':' suite)?; 58try_stmt: ('try' ':' suite (except_clause ':' suite)+ 59 ('else' ':' suite)? | 'try' ':' suite 'finally' ':' suite); 60// NB compile.c makes sure that the default except clause is last 61except_clause: 'except' (test (',' test)?)?; 62suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT; 63 64test: and_test ('or' and_test)* | lambdef; 65and_test: not_test ('and' not_test)*; 66not_test: 'not' not_test | comparison; 67comparison: expr (comp_op expr)*; 68comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'; 69expr: xor_expr ('|' xor_expr)*; 70xor_expr: and_expr ('^' and_expr)*; 71and_expr: shift_expr ('&' shift_expr)*; 72shift_expr: arith_expr (('<<'|'>>') arith_expr)*; 73arith_expr: term (('+'|'-') term)*; 74term: factor (('*'|'/'|'%'|'//') factor)*; 75factor: ('+'|'-'|'~') factor | power; 76power: atom trailer* ('**' factor)*; 77atom: LP testlist? RP | LB listmaker? RB | LC dictmaker? RC | '`' testlist '`' | NAME | NUMBER | STRING+; 78listmaker: test ( list_for | (',' test)* ','? ); 79lambdef: 'lambda' varargslist? ':' test; 80trailer: LP arglist? RP | LB subscriptlist RB | '.' NAME; 81subscriptlist: subscript (',' subscript)* ','?; 82subscript: '.' '.' '.' | test | test? ':' test? sliceop?; 83sliceop: ':' test?; 84exprlist: expr (',' expr)* ','?; 85testlist: test (',' test)* ','?; 86testlist_safe: test ((',' test)+ ','?)?; 87dictmaker: test ':' test (',' test ':' test)* ','?; 88 89classdef: 'class' NAME (LP testlist RP)? ':' suite; 90 91arglist: (argument ',')* (argument ','?| '*' test (',' '**' test)? | '**' test); 92argument: (NAME '=')? test; 93 94list_iter: list_for | list_if; 95list_for: 'for' exprlist 'in' testlist_safe list_iter?; 96list_if: 'if' test list_iter?; 97 98/* additional material from http://www.python.org/doc/current/ref/grammar.txt */ 99 100NEWLINE: '\n'; 101INDENT: [ if (!python_indent(&$g)) return -1; ] ; 102DEDENT: [ if (!python_dedent(&$g)) return -1; ] ; 103NAME ::= (letter|'_') (letter | digit | '_')*; 104letter ::= "[a-zA-Z]"; 105digit ::= "[0-9]"; 106STRING ::= stringprefix?(shortstring | longstring); 107shortstring ::= "'" shortstringsingleitem* "'" 108 | '"' shortstringdoubleitem* '"'; 109longstring ::= "'''" longstringitem* "'''" 110 | '"""' longstringitem* '"""'; 111shortstringsingleitem ::= shortstringsinglechar | escapeseq; 112shortstringdoubleitem ::= shortstringdoublechar | escapeseq; 113longstringitem ::= longstringchar | escapeseq; 114shortstringsinglechar ::= "[^\\\n\']"; 115shortstringdoublechar ::= "[^\\\n\"]"; 116longstringchar ::= "[^\\]"; 117stringprefix ::= 'r' | 'u' | 'ur' | 'R' | 'U' | 'UR' | 'Ur' | 'uR'; 118escapeseq ::= "\\[^]"; 119NUMBER ::= integer | longinteger | floatnumber | imagnumber; 120integer ::= decimalinteger | octinteger | hexinteger; 121decimalinteger ::= nonzerodigit digit* | '0'; 122octinteger ::= '0' octdigit+; 123hexinteger ::= '0' ('x' | 'X') hexdigit+; 124floatnumber ::= pointfloat | exponentfloat; 125pointfloat ::= intpart? fraction | intpart '.'; 126exponentfloat ::= (intpart | pointfloat) exponent; 127intpart ::= digit+; 128fraction ::= "." digit+; 129exponent ::= ("e" | "E") ("+" | "-")? digit+; 130imagnumber ::= (floatnumber | intpart) ("j" | "J"); 131longinteger ::= integer ("l" | "L"); 132nonzerodigit ::= "[1-9]"; 133digit ::= "[0-9]"; 134octdigit ::= "[0-7]"; 135hexdigit ::= digit | "[a-fA-F]"; 136 137LP ::= '(' [ $g->implicit_line_joining++; ]; 138RP ::= ')' [ $g->implicit_line_joining--; ]; 139LB ::= '[' [ $g->implicit_line_joining++; ]; 140RB ::= ']' [ $g->implicit_line_joining--; ]; 141LC ::= '{' [ $g->implicit_line_joining++; ]; 142RC ::= '}' [ $g->implicit_line_joining--; ]; 143 144{ 145 146#include "dparse.h" 147#include <stdlib.h> 148#include <stdio.h> 149#include <string.h> 150 151void print_pg(PythonGlobals *pg, char *s) { 152 int i, n; 153 n = pg->current_indent - pg->indent_stack; 154 for (i = 0; i < n; i++) 155 printf("%d ", pg->indent_stack[i]); 156 printf("%s\n", s); 157} 158 159void python_whitespace(struct D_Parser *parser, d_loc_t *loc, void **p_globals) { 160 char *p = loc->s; 161 PythonGlobals *pg = *p_globals; 162 int i; 163 if (!pg) { 164 *p_globals = (void**)(pg = (PythonGlobals*)malloc(sizeof(PythonGlobals))); 165 memset(pg, 0, sizeof(*pg)); 166 pg->current_indent = &pg->indent_stack[2]; 167 } 168 if (parser->loc.s == p) 169 i = 0; 170 else 171 i = p[-1] == '\n' ? 0 : -1; 172 while (1) { 173 switch (*p) { 174 case '#': p++; while (*p && *p != '\n') p++; break; 175 case ' ': p++; if (i >= 0) i++; break; 176 case '\t': p++; if (i >= 0) i = (i + 7) & ~7; break; 177 case '\n': if (i >= 0 || pg->implicit_line_joining) { loc->line++; p++; i = 0; break; } 178 /* else fall through */ 179 default: goto Ldone; 180 } 181 } 182 Ldone:; 183 if (i >= 0 && !pg->implicit_line_joining && *p != '\n') 184 if (i != pg->current_indent[-1]) /* || i != pg->current_indent[-2]) */ { 185 *pg->current_indent++ = i; 186 /* print_pg(pg, "-"); */ 187 } 188 loc->s = p; 189} 190 191int python_indent(PythonGlobals **p_globals) { 192 PythonGlobals *pg = *p_globals; 193 if (pg) { 194 if (pg->current_indent[-1] > pg->current_indent[-2]) 195 return 1; 196 if (pg->current_indent[-1] && pg->current_indent[-1] == pg->current_indent[-2] && 197 pg->current_indent[-2] > pg->current_indent[-3]) { 198 pg->current_indent--; 199 /* print_pg(pg, ">"); */ 200 return 1; 201 } 202 } 203 return 0; 204} 205 206int python_dedent(PythonGlobals **p_globals) { 207 int x; 208 PythonGlobals *pg = *p_globals; 209 if (pg && pg->current_indent[-1] < pg->current_indent[-2]) { 210 pg->current_indent--; 211 x = pg->current_indent[-1] = pg->current_indent[0]; 212 while (x == pg->current_indent[-2]) pg->current_indent--; 213 /* print_pg(pg, "<"); */ 214 return 1; 215 } 216 return 0; 217} 218 219} 220 221