// -*- java -*- // Copyright © Corporation for National Research Initiatives options { // only non-defaults are given here. NODE_SCOPE_HOOK = true; // call jjtree*NodeScope() STATIC = false; // multiple parsers COMMON_TOKEN_ACTION = true; // CommonTokenAction(Token) // DEBUG_PARSER = true; // DEBUG_TOKEN_MANAGER = true; } PARSER_BEGIN(PythonGrammar) package org.python.parser; public class PythonGrammar { void jjtreeOpenNodeScope(Node n) { ((SimpleNode)n).beginLine = getToken(1).beginLine; ((SimpleNode)n).beginColumn = getToken(1).beginColumn; } void jjtreeCloseNodeScope(Node n) { ((SimpleNode)n).endLine = getToken(0).endLine; ((SimpleNode)n).endColumn = getToken(0).endColumn; } } PARSER_END(PythonGrammar) TOKEN_MGR_DECLS: { int indentation[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; int level = 0; int dedents = 0; int parens = 0; int indent; boolean seen_eof = false; boolean single_input = false; boolean compound = false; public boolean forcedNewline = false; // static Token addDedent(Token previous) { // Token t = new Token(); // t.kind = DEDENT; // t.beginLine = previous.beginLine; // t.endLine = previous.endLine; // t.beginColumn = previous.beginColumn; // t.endColumn = previous.endColumn; // t.image = ""; // t.specialToken = null; // t.next = null; // previous.next = t; // return t; // } void CommonTokenAction(Token t) { // if (t.kind == EOF) { // //System.out.println("EOF: "+single_input+", "+curLexState); // if (!single_input) { // if (curLexState == DEFAULT) { // t.kind = NEWLINE; // } // else { // t.kind = DEDENT; // level -= 1; // } // while (level-- >= 0) // t = addDedent(t); // //t = addDedent(t); // t.kind = EOF; // t.image = ""; // } // } } } SKIP : { | "\t" | "\014" | | } TOKEN : { } TOKEN : /* a nicer alternative for the whitespace programming misery */ { < INDENT: "{{" > | < DEDENT: "}}" > } //SKIP : //{ // //| "\t" //| "\014" //| //| // { // if (parens == 0) { // indent = 0; // input_stream.backup(1); // if (level == 0) // SwitchTo(FORCE_NEWLINE1); // else // SwitchTo(FORCE_NEWLINE2); // } // } //} // // // TOKEN : //{ : INDENTATION_UNCHANGED } // // // TOKEN : //{ { matchedToken.kind = NEWLINE; }: INDENTING } // // // TOKEN : //{ // // { // Token t1 = matchedToken; // //System.out.println("final_newline: "+level); // t1.kind = DEDENT; // while (level-- > 0) // t1 = addDedent(t1); // t1.kind = NEWLINE; // } : DEFAULT //} // // SKIP : //{ // "\t" // { // indent = (indent/8+1)*8; // if (indent == indentation[level]) // SwitchTo(INDENTATION_UNCHANGED); // else // SwitchTo(INDENTING); // } //| " " // { // indent += 1; // if (indent == indentation[level]) // SwitchTo(INDENTATION_UNCHANGED); // else // SwitchTo(INDENTING); // } //| "\014" // { // indent = 0; // if (indent == indentation[level]) // SwitchTo(INDENTATION_UNCHANGED); // else // SwitchTo(INDENTING); // } //| // { // // if (parens == 0 && single_input && indent==0) { // //System.out.println("force newline"); // //backup a character! // forcedNewline = true; // input_stream.backup(1); // SwitchTo(FORCE_NEWLINE); // } // else { // //doPrompt(); // indent = 0; // if (indent == indentation[level]) // SwitchTo(INDENTATION_UNCHANGED); // else // SwitchTo(INDENTING); // } // } //} // // // // SKIP : //{ // <""> : DEFAULT //} // // // TOKEN : //{ // // { // if (indent > indentation[level]) { // level++; // indentation[level] = indent; // matchedToken.kind=INDENT; // matchedToken.image = ""; // } // else { // Token t = matchedToken; // level -= 1; // while (level > 0 && indent < indentation[level]) { // level--; // t = addDedent(t); // } // if (indent != indentation[level]) { // throw new TokenMgrError("inconsistent dedent", // t.endLine, t.endColumn); // } // t.next = null; // } // } : DEFAULT //} // // // TOKEN : //{ // < INDENT:""> ////| < DEDENT:""> //} // // // SPECIAL_TOKEN: /* COMMENTS */ //{ // { indent = 0; } //} TOKEN : /* SEPARATORS */ { < LPAREN: "(" > {parens++;} | < RPAREN: ")" > {parens--;} | < LBRACE: "{" > {parens++;} | < RBRACE: "}" > {parens--;} | < LBRACKET: "[" > {parens++;} | < RBRACKET: "]" > {parens--;} | < SEMICOLON: ";" > | < COMMA: "," > | < DOT: "." > | < COLON: ":" > } TOKEN : /* OPERATORS */ { < PLUS: "+" > | < MINUS: "-" > | < MULTIPLY: "*" > | < DIVIDE: "/" > | < POWER: "**" > | < LSHIFT: "<<" > | < RSHIFT: ">>" > | < MODULO: "%" > | < NOT: "~" > | < XOR: "^" > | < OR: "|" > | < AND: "&" > | < EQUAL: "=" > | < GREATER: ">" > | < LESS: "<" > | < EQEQUAL: "==" > | < EQLESS: "<=" > | < EQGREATER: ">=" > | < LESSGREATER: "<>" > | < NOTEQUAL: "!=" > | < PLUSEQ: "+=" > | < MINUSEQ: "-=" > | < MULTIPLYEQ: "*=" > | < DIVIDEEQ: "/=" > | < MODULOEQ: "%=" > | < ANDEQ: "&=" > | < OREQ: "|=" > | < XOREQ: "^=" > | < LSHIFTEQ: "<<=" > | < RSHIFTEQ: ">>=" > | < POWEREQ: "**=" > } TOKEN : /* KEYWORDS */ { < OR_BOOL: "or" > | < AND_BOOL: "and" > | < NOT_BOOL: "not" > | < IS: "is" > | < IN: "in" > | < LAMBDA: "lambda" > | < IF: "if" > | < ELSE: "else" > | < ELIF: "elif" > | < WHILE: "while" > | < FOR: "for" > | < TRY: "try" > | < EXCEPT: "except" > | < DEF: "def" > | < CLASS: "class" > | < FINALLY: "finally" > | < PRINT: "print" > | < PASS: "pass" > | < BREAK: "break" > | < CONTINUE: "continue" > | < RETURN: "return" > | < IMPORT: "import" > | < FROM: "from" > | < DEL: "del" > | < RAISE: "raise" > | < GLOBAL: "global" > | < EXEC: "exec" > | < ASSERT: "assert" > | < AS: "as" > } TOKEN : /* Python identifiers */ { < NAME: ( | )* > | < #LETTER: ["_","a"-"z","A"-"Z"] > } TOKEN : /* Numeric literals */ { < DECNUMBER: ["1"-"9"] (["0"-"9"])* (["j", "J", "l", "L"])? | "0" ["j", "J"] > | < HEXNUMBER: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+ (["l","L"])? > | < OCTNUMBER: "0" (["0"-"7"])* (["l","L"])? > | < FLOAT: (["0"-"9"])+ "." (["0"-"9"])* ()? (["j", "J"])? | "." (["0"-"9"])+ ()? (["j", "J"])? | (["0"-"9"])+ (["j", "J"])? > | < #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ > | < #DIGIT: ["0" - "9"] > } /*TOKEN : { { int nquotes = matchedToken.image.length() > 2 ? 3 : 1; char quote = matchedToken.image.charAt(matchedToken.image.length()-1); } }*/ MORE : /* Strings */ { < (["u", "U"])? (["r", "R"])? "'" > : IN_STRING11 | < (["u", "U"])? (["r", "R"])? "\"" > : IN_STRING21 | < (["u", "U"])? (["r", "R"])? "'''" > : IN_STRING13 | < (["u", "U"])? (["r", "R"])? "\"\"\"" > : IN_STRING23 } TOKEN : { { matchedToken.image = image.toString(); } : DEFAULT} TOKEN : { { matchedToken.image = image.toString(); } : DEFAULT} TOKEN : { { matchedToken.image = image.toString(); } : DEFAULT} TOKEN : { { matchedToken.image = image.toString(); } : DEFAULT} MORE: { <"\\\r\n"> { image.setLength(image.length()-3); } | <("\\" ("\n"|"\r"))> { image.setLength(image.length()-2); } } MORE: { <("\\" ("\\"|"'")) | ~["\n","\r"]> } MORE: { <("\\" ("\\"|"\"")) | ~["\n","\r"]> } MORE: { "\\'''" } MORE: { "\\\"\"\"" } MORE: { <"\r\n"> { int l = image.length(); image.setLength(l-1); image.setCharAt(l-2, '\n'); } | <"\n"> | <"\r"> { image.setCharAt(image.length()-1, '\n'); } | <~["\n","\r"]> } //single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE SimpleNode single_input(): {token_source.single_input=true;} { ( | simple_stmt() | compound_stmt() ) { return jjtThis; } } //file_input: (NEWLINE | stmt)* ENDMARKER SimpleNode file_input(): {token_source.single_input=false;} { ( | stmt())* { return jjtThis; } } //eval_input: testlist NEWLINE* ENDMARKER SimpleNode eval_input(): {token_source.single_input=false;} { SmartTestList() ()* { return jjtThis; } } //funcdef: 'def' NAME parameters ':' suite void funcdef(): {} { AnyName() parameters() suite() } //parameters: '(' [varargslist] ')' void parameters() #void: {} { [varargslist()] } //varargslist: (fpdef ['=' test] ',')* ('*' NAME [',' ('**'|'*' '*') NAME] | ('**'|'*' '*') NAME) | fpdef ['=' test] (',' fpdef ['=' test])* [','] void varargslist(): {} { defaultarg() (LOOKAHEAD(2) defaultarg())* [LOOKAHEAD(3) ExtraArgList()] [LOOKAHEAD(2) ExtraKeywordList()] [] | ( LOOKAHEAD(2) ExtraArgList() [ ExtraKeywordList()] | ExtraKeywordList() ) } void ExtraArgList(): {} { Name() } void ExtraKeywordList(): {} { (| ) Name() } void defaultarg(): {} { fpdef() [ test()] } //fpdef: NAME | '(' fplist ')' void fpdef() #void: {} { Name() | fplist() } //fplist: fpdef (',' fpdef)* [','] void fplist(): {} { fpdef() (LOOKAHEAD(2) fpdef())* [] } //stmt: simple_stmt | compound_stmt void stmt() #void: {} { simple_stmt() | compound_stmt() } //simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE void simple_stmt() #void: {} //{ small_stmt() (LOOKAHEAD(2) small_stmt())* [] { small_stmt() (LOOKAHEAD(2) small_stmt())* } //small_stmt: expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | exec_stmt | assert_stmt void small_stmt() #void: {} { expr_stmt() | print_stmt() | del_stmt() | pass_stmt() | flow_stmt() | import_stmt() | global_stmt() | exec_stmt() | assert_stmt() } //expr_stmt: testlist (augassign testlist | ('=' testlist)*) void expr_stmt(): {} { SmartTestList() ( SmartTestList() #aug_plus(2) | SmartTestList() #aug_minus(2) | SmartTestList() #aug_multiply(2) | SmartTestList() #aug_divide(2) | SmartTestList() #aug_modulo(2) | SmartTestList() #aug_and(2) | SmartTestList() #aug_or(2) | SmartTestList() #aug_xor(2) | SmartTestList() #aug_lshift(2) | SmartTestList() #aug_rshift(2) | SmartTestList() #aug_power(2) | ( SmartTestList())* ) } //print_stmt: 'print' (test ',')* [test] | 'print' '>>' test (, test)+ [,] void print_stmt() #print_stmt: {} { LOOKAHEAD(2) test() #print_ext(1) [ (LOOKAHEAD(2) test())+ [Comma()] ] | LOOKAHEAD(2) test() (LOOKAHEAD(2) test())* [Comma()] | } //del_stmt: 'del' exprlist void del_stmt(): {} { exprlist() } //pass_stmt: 'pass' void pass_stmt(): {} { } //flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt void flow_stmt() #void: {} { #break_stmt(0) | #continue_stmt(0) | return_stmt() | raise_stmt() } //return_stmt: 'return' [testlist] void return_stmt(): {} { [SmartTestList()] } //raise_stmt: 'raise' [test [',' test [',' test]]] void raise_stmt(): {} { [test() [ test() [ test()]]] } //import_stmt: 'import' dotted_name (',' dotted_name)* | 'from' dotted_name 'import' ('*' | NAME (',' NAME)*) void import_stmt() #void: {} { Import() | ImportFrom() } void Import(): {} { dotted_as_name() ( dotted_as_name())* } void ImportFrom(): {} { dotted_name() ( | import_as_name() ( import_as_name())* ) } //dotted_as_name: dotted_name [NAME NAME] void dotted_as_name() #void:{} { dotted_name() [ Name() #dotted_as_name(2)] } //dotted_name: NAME ('.' NAME)* void dotted_name(): {} { AnyName() ( AnyName())* } //import_as_name: NAME [NAME NAME] void import_as_name() #void: {} { AnyName() [ Name() #import_as_name(2)] } //global_stmt: 'global' NAME (',' NAME)* void global_stmt(): {} { Name() ( Name())* } //exec_stmt: 'exec' expr ['in' test [',' test]] void exec_stmt(): {} { expr() [ test() [ test()]] } //assert_stmt: 'assert' test [',' test] void assert_stmt(): {} { test() [ test()] } //compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef void compound_stmt() #void : { token_source.compound = true; } {if_stmt() | while_stmt() | for_stmt() | try_stmt() | funcdef() | classdef()} //if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] void if_stmt(): {} { test() suite() ( test() suite())* [ suite()] } //while_stmt: 'while' test ':' suite ['else' ':' suite] void while_stmt(): {} { test() suite() [ suite()] } //for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite] void for_stmt(): {} { exprlist() SmartTestList() suite() [ suite()] } //try_stmt: ('try' ':' suite (except_clause ':' suite)+ #diagram:break // ['else' ':' suite] | 'try' ':' suite 'finally' ':' suite) void try_stmt(): {} { suite() ( ( except_clause() suite())+ [ suite()] | suite()) } //except_clause: 'except' [test [',' test]] void except_clause(): {} { [test() [ test()]] } //suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT void suite(): {} //{ simple_stmt() | (stmt())+ } { simple_stmt() | (stmt())+ } //test: and_test ('or' and_test)* | lambdef void test() #void: {} { lambdef() | and_test() ( and_test() #or_boolean(2))* } //and_test: not_test ('and' not_test)* void and_test() #void: {} { not_test() ( not_test() #and_boolean(2))* } //not_test: 'not' not_test | comparison void not_test() #void: {} { not_test() #not_1op(1) | comparison() } //comparison: expr (comp_op expr)* void comparison() #void: {} { (expr() (comp_op() expr())*) #comparision(>1) } //comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not' void comp_op() #void: {} { #less_cmp(0) | #greater_cmp(0) | #equal_cmp(0) | #greater_equal_cmp(0) | #less_equal_cmp(0) | #notequal_cmp(0) | #notequal_cmp(0) | #in_cmp(0) | #not_in_cmp(0) | LOOKAHEAD(2) #is_not_cmp(0) | #is_cmp(0) } //expr: xor_expr ('|' xor_expr)* void expr() #void : {} { xor_expr() ( xor_expr() #or_2op(2))* } //xor_expr: and_expr ('^' and_expr)* void xor_expr() #void : {} { and_expr() ( and_expr() #xor_2op(2))* } //and_expr: shift_expr ('&' shift_expr)* void and_expr() #void : {} { shift_expr() ( shift_expr() #and_2op(2))* } //shift_expr: arith_expr (('<<'|'>>') arith_expr)* void shift_expr() #void : {} { arith_expr() ( arith_expr() #lshift_2op(2) | arith_expr() #rshift_2op(2) )* } //arith_expr: term (('+'|'-') term)* void arith_expr() #void : {} { term() ( term() #add_2op(2) | term() #sub_2op(2) )* } //term: factor (('*'|'/'|'%') factor)* void term() #void : {} { factor() ( factor() #mul_2op(2) | factor() #div_2op(2) | factor() #mod_2op(2) )* } //factor: ('+'|'-'|'~') factor | power void factor() #void: {} { factor() #pos_1op(1) | factor() #neg_1op(1) | factor() #invert_1op(1) | power() } /*Modified, no recursion*/ //power: atom trailer* ('**' factor)* void power() #void: {} { atomtrailer() (LOOKAHEAD(2) factor() #pow_2op(2))* } //trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME void atomtrailer() #void: {} { atom() ( (LOOKAHEAD(2) #Call_Op(1) | arglist() #Call_Op(2)) | subscriptlist() #Index_Op(2) | AnyName() #Dot_Op(2) )* } //atom: '(' [testlist] ')' | '[' [testlist] ']' | '{' [dictmaker] '}' | '`' testlist '`' | NAME | NUMBER | STRING+ void atom() #void: {} { LOOKAHEAD(2) ( ) #tuple | ( [SmartTestList()] ) | ( [listmaker()] ) #list | ( [dictmaker()] ) #dictionary | "`" SmartTestList() "`" #str_1op(1) | Name() | Number() | String() (String() #strjoin(2))* } //lambdef: 'lambda' [varargslist] ':' test void lambdef():{} { [varargslist()] test() } //subscriptlist: subscript (',' subscript)* [','] void subscriptlist() #void: {} { (subscript() (LOOKAHEAD(2) subscript())* [Comma()]) #tuple(>1) } //subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop] void subscript() #void: {} { #Ellipses | (test() (slice())?) #Slice(>1) | slice() #Slice(>0) } //sliceop: ':' [test] void slice() #void: {} { Colon() [test()] (Colon() [test()])? } void Colon(): {} {} void Comma(): {} {} //exprlist: expr (',' expr)* [','] void exprlist() #void: {} { (expr() (LOOKAHEAD(2) expr())* [Comma()]) #tuple(>1) } //testlist: test (',' test)* [','] void SmartTestList() #void: {} { (test() (LOOKAHEAD(2) test())* [Comma()]) #tuple(>1) } //testlist: test (',' test)* [','] void testlist() #void: {} { test() (LOOKAHEAD(2) test())* []} //dictmaker: test ':' test (',' test ':' test)* [','] void dictmaker() #void: {} {test() test() (LOOKAHEAD(2) test() test())* []} //listmaker: test ( list_for | (',' test)* [','] ) void listmaker() #void: {} { test() ( list_for() | (LOOKAHEAD(2) test())* [Comma()] #tuple(>1)) } //list_iter: [list_for | list_if] void list_iter(): {} { [ (list_for() | list_if()) ] } //list_for: 'for' exprlist 'in' testlist list_iter void list_for() #for_stmt: {} { exprlist() SmartTestList() list_iter() } //list_if: 'if' test list_iter void list_if() #if_stmt: {} { test() list_iter() } //classdef: 'class' NAME ['(' testlist ')'] ':' suite void classdef(): {} { Name() [ testlist() ] suite()} //arglist: (argument ',')* // (argument [',']| '*' test [',' '**' test] | '**' test) void arglist(): {} { normalargs() [ [LOOKAHEAD(2) ExtraArgValueList() [ ExtraKeywordValueList() ] | ExtraKeywordValueList()]] | [LOOKAHEAD(2) ExtraArgValueList() [ ExtraKeywordValueList() ] | ExtraKeywordValueList()] } void normalargs() #void: {} { argument() (LOOKAHEAD(2) argument())* } void ExtraArgValueList(): {} { test() } void ExtraKeywordValueList(): {} { (| ) test() } //argument: [test '='] test # Really [keyword '='] test void argument() #void: {} { ([LOOKAHEAD(2) AnyName() ] test()) #Keyword(>1) } void Number() #void : { Token t; } { ( t= { jjtThis.setInteger(t.image.substring(2,t.image.length()), 16); } )#Int | ( t= { jjtThis.setInteger(t.image, 8); } )#Int | ( t= { jjtThis.setInteger(t.image, 10); } )#Int | ( t= { jjtThis.setFloat(t.image); } )#Float } void Complex(): {} { } void Name() #Name: { Token t; } { t = { jjtThis.setInfo(t.image); } | t = { jjtThis.setInfo(t.image); } } void String() #void : { Token t; } { ( t= { jjtThis.setString(t.image, 1); } )#String | ( t= { jjtThis.setString(t.image, 1); } )#String | ( t= { jjtThis.setString(t.image, 3); } )#String | ( t= { jjtThis.setString(t.image, 3); } )#String } void AnyName() #void: { Token t; } { ( t= { jjtThis.setInfo(t.image); } )#Name | ( t = { jjtThis.setInfo(t.image); } )#Name | ( t = { jjtThis.setInfo(t.image); } )#Name | ( t = { jjtThis.setInfo(t.image); } )#Name | ( t = { jjtThis.setInfo(t.image); } )#Name | ( t = { jjtThis.setInfo(t.image); } )#Name | ( t = { jjtThis.setInfo(t.image); } )#Name | ( t = { jjtThis.setInfo(t.image); } )#Name | ( t = { jjtThis.setInfo(t.image); } )#Name | ( t = { jjtThis.setInfo(t.image); } )#Name | ( t = { jjtThis.setInfo(t.image); } )#Name | ( t = { jjtThis.setInfo(t.image); } )#Name | ( t = { jjtThis.setInfo(t.image); } )#Name | ( t = { jjtThis.setInfo(t.image); } )#Name | ( t = { jjtThis.setInfo(t.image); } )#Name | ( t = { jjtThis.setInfo(t.image); } )#Name | ( t = { jjtThis.setInfo(t.image); } )#Name | ( t = { jjtThis.setInfo(t.image); } )#Name | ( t = { jjtThis.setInfo(t.image); } )#Name | ( t = { jjtThis.setInfo(t.image); } )#Name | ( t = { jjtThis.setInfo(t.image); } )#Name | ( t = { jjtThis.setInfo(t.image); } )#Name | ( t = { jjtThis.setInfo(t.image); } )#Name | ( t = { jjtThis.setInfo(t.image); } )#Name | ( t = { jjtThis.setInfo(t.image); } )#Name | ( t = { jjtThis.setInfo(t.image); } )#Name | ( t = { jjtThis.setInfo(t.image); } )#Name | ( t = { jjtThis.setInfo(t.image); } )#Name | ( t = { jjtThis.setInfo(t.image); } )#Name | ( t = { jjtThis.setInfo(t.image); } )#Name }