summaryrefslogtreecommitdiff
path: root/etc/grammars/python.wy
diff options
context:
space:
mode:
Diffstat (limited to 'etc/grammars/python.wy')
-rw-r--r--etc/grammars/python.wy1132
1 files changed, 1132 insertions, 0 deletions
diff --git a/etc/grammars/python.wy b/etc/grammars/python.wy
new file mode 100644
index 00000000000..a0af813e5e8
--- /dev/null
+++ b/etc/grammars/python.wy
@@ -0,0 +1,1132 @@
+;;; python.wy -- LALR grammar for Python
+
+;; Copyright (C) 2002-2011 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2010 Python Software Foundation
+
+;; Author: Richard Kim <ryk@dspwiz.com>
+;; Maintainer: Richard Kim <ryk@dspwiz.com>
+;; Created: June 2002
+;; Keywords: syntax
+;;
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; This is an LALR python parser that follows the official python
+;; grammar closely with very few exceptions. The Python grammar is
+;; used and reproduced under the following license:
+;;
+;; PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
+;; --------------------------------------------
+;; 1. This LICENSE AGREEMENT is between the Python Software Foundation
+;; ("PSF"), and the Individual or Organization ("Licensee") accessing
+;; and otherwise using this software ("Python") in source or binary
+;; form and its associated documentation.
+;;
+;; 2. Subject to the terms and conditions of this License Agreement,
+;; PSF hereby grants Licensee a nonexclusive, royalty-free, world-wide
+;; license to reproduce, analyze, test, perform and/or display
+;; publicly, prepare derivative works, distribute, and otherwise use
+;; Python alone or in any derivative version, provided, however, that
+;; PSF's License Agreement and PSF's notice of copyright, i.e.,
+;; "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
+;; 2009, 2010 Python Software Foundation; All Rights Reserved" are
+;; retained in Python alone or in any derivative version prepared by
+;; Licensee.
+;;
+;; 3. In the event Licensee prepares a derivative work that is based
+;; on or incorporates Python or any part thereof, and wants to make
+;; the derivative work available to others as provided herein, then
+;; Licensee hereby agrees to include in any such work a brief summary
+;; of the changes made to Python.
+;;
+;; 4. PSF is making Python available to Licensee on an "AS IS"
+;; basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+;; IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
+;; DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
+;; FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
+;; INFRINGE ANY THIRD PARTY RIGHTS.
+;;
+;; 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
+;; FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A
+;; RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, OR
+;; ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+;;
+;; 6. This License Agreement will automatically terminate upon a
+;; material breach of its terms and conditions.
+;;
+;; 7. Nothing in this License Agreement shall be deemed to create any
+;; relationship of agency, partnership, or joint venture between PSF
+;; and Licensee. This License Agreement does not grant permission to
+;; use PSF trademarks or trade name in a trademark sense to endorse or
+;; promote products or services of Licensee, or any third party.
+;;
+;; 8. By copying, installing or otherwise using Python, Licensee
+;; agrees to be bound by the terms and conditions of this License
+;; Agreement.
+
+;;; To do:
+;;
+;; * Verify that semantic-lex-python-number regexp is correct.
+
+;; --------
+;; Settings
+;; --------
+
+%package wisent-python-wy
+
+%languagemode python-mode
+
+;; The default start symbol
+%start goal
+;; Alternate entry points
+;; - Needed by partial re-parse
+%start function_parameter
+%start paren_class
+%start indented_block
+;; - Needed by EXPANDFULL clauses
+%start function_parameters
+%start paren_classes
+%start indented_block_body
+
+;; -------------------------------
+;; Misc. Python specific terminals
+;; -------------------------------
+;; The value of these tokens are for documentation only, they are not
+;; used by the lexer.
+%token <charquote> BACKSLASH "\\"
+%token <newline> NEWLINE "\n"
+%token <indentation> INDENT "^\\s-+"
+%token <indentation> DEDENT "[^:INDENT:]"
+%token <indentation> INDENT_BLOCK "(INDENT DEDENT)"
+
+;; -----------------------------
+;; Block & Parenthesis terminals
+;; -----------------------------
+%type <block> ;;syntax "\\s(\\|\\s)" matchdatatype block
+
+%token <block> PAREN_BLOCK "(LPAREN RPAREN)"
+%token <block> BRACE_BLOCK "(LBRACE RBRACE)"
+%token <block> BRACK_BLOCK "(LBRACK RBRACK)"
+
+%token <open-paren> LPAREN "("
+%token <close-paren> RPAREN ")"
+%token <open-paren> LBRACE "{"
+%token <close-paren> RBRACE "}"
+%token <open-paren> LBRACK "["
+%token <close-paren> RBRACK "]"
+
+;; ------------------
+;; Operator terminals
+;; ------------------
+%type <punctuation> ;;syntax "\\(\\s.\\|\\s$\\|\\s'\\)+" matchdatatype string
+
+%token <punctuation> LTLTEQ "<<="
+%token <punctuation> GTGTEQ ">>="
+%token <punctuation> EXPEQ "**="
+%token <punctuation> DIVDIVEQ "//="
+%token <punctuation> DIVDIV "//"
+%token <punctuation> LTLT "<<"
+%token <punctuation> GTGT ">>"
+%token <punctuation> EXPONENT "**"
+%token <punctuation> EQ "=="
+%token <punctuation> GE ">="
+%token <punctuation> LE "<="
+%token <punctuation> PLUSEQ "+="
+%token <punctuation> MINUSEQ "-="
+%token <punctuation> MULTEQ "*="
+%token <punctuation> DIVEQ "/="
+%token <punctuation> MODEQ "%="
+%token <punctuation> AMPEQ "&="
+%token <punctuation> OREQ "|="
+%token <punctuation> HATEQ "^="
+%token <punctuation> LTGT "<>"
+%token <punctuation> NE "!="
+%token <punctuation> HAT "^"
+%token <punctuation> LT "<"
+%token <punctuation> GT ">"
+%token <punctuation> AMP "&"
+%token <punctuation> MULT "*"
+%token <punctuation> DIV "/"
+%token <punctuation> MOD "%"
+%token <punctuation> PLUS "+"
+%token <punctuation> MINUS "-"
+%token <punctuation> PERIOD "."
+%token <punctuation> TILDE "~"
+%token <punctuation> BAR "|"
+%token <punctuation> COLON ":"
+%token <punctuation> SEMICOLON ";"
+%token <punctuation> COMMA ","
+%token <punctuation> ASSIGN "="
+%token <punctuation> BACKQUOTE "`"
+
+
+;; -----------------
+;; Literal terminals
+;; -----------------
+%token <string> STRING_LITERAL
+
+%type <number> ;;syntax semantic-lex-number-expression
+%token <number> NUMBER_LITERAL
+
+%type <symbol> ;;syntax "\\(\\sw\\|\\s_\\)+"
+%token <symbol> NAME
+
+;; -----------------
+;; Keyword terminals
+;; -----------------
+%type <keyword> ;;syntax "\\(\\sw\\|\\s_\\)+" matchdatatype keyword
+
+%keyword AND "and"
+%put AND summary
+"Logical AND binary operator ... "
+
+%keyword AS "as"
+%put AS summary
+"EXPR as NAME makes value of EXPR available as variable NAME"
+
+%keyword ASSERT "assert"
+%put ASSERT summary
+"Raise AssertionError exception if <expr> is false"
+
+%keyword BREAK "break"
+%put BREAK summary
+"Terminate 'for' or 'while' loop"
+
+%keyword CLASS "class"
+%put CLASS summary
+"Define a new class"
+
+%keyword CONTINUE "continue"
+%put CONTINUE summary
+"Skip to the next iteration of enclosing 'for' or 'while' loop"
+
+%keyword DEF "def"
+%put DEF summary
+"Define a new function"
+
+%keyword DEL "del"
+%put DEL summary
+"Delete specified objects, i.e., undo what assignment did"
+
+%keyword ELIF "elif"
+%put ELIF summary
+"Shorthand for 'else if' following an 'if' statement"
+
+%keyword ELSE "else"
+%put ELSE summary
+"Start the 'else' clause following an 'if' statement"
+
+%keyword EXCEPT "except"
+%put EXCEPT summary
+"Specify exception handlers along with 'try' keyword"
+
+%keyword EXEC "exec"
+%put EXEC summary
+"Dynamically execute Python code"
+
+%keyword FINALLY "finally"
+%put FINALLY summary
+"Specify code to be executed after 'try' statements whether or not an exception occurred"
+
+%keyword FOR "for"
+%put FOR summary
+"Start a 'for' loop"
+
+%keyword FROM "from"
+%put FROM summary
+"Modify behavior of 'import' statement"
+
+%keyword GLOBAL "global"
+%put GLOBAL summary
+"Declare one or more symbols as global symbols"
+
+%keyword IF "if"
+%put IF summary
+"Start 'if' conditional statement"
+
+%keyword IMPORT "import"
+%put IMPORT summary
+"Load specified modules"
+
+%keyword IN "in"
+%put IN summary
+"Part of 'for' statement "
+
+%keyword IS "is"
+%put IS summary
+"Binary operator that tests for object equality"
+
+%keyword LAMBDA "lambda"
+%put LAMBDA summary
+"Create anonymous function"
+
+%keyword NOT "not"
+%put NOT summary
+"Unary boolean negation operator"
+
+%keyword OR "or"
+%put OR summary
+"Binary logical 'or' operator"
+
+%keyword PASS "pass"
+%put PASS summary
+"Statement that does nothing"
+
+%keyword PRINT "print"
+%put PRINT summary
+"Print each argument to standard output"
+
+%keyword RAISE "raise"
+%put RAISE summary
+"Raise an exception"
+
+%keyword RETURN "return"
+%put RETURN summary
+"Return from a function"
+
+%keyword TRY "try"
+%put TRY summary
+"Start of statements protected by exception handlers"
+
+%keyword WHILE "while"
+%put WHILE summary
+"Start a 'while' loop"
+
+%keyword YIELD "yield"
+%put YIELD summary
+"Create a generator function"
+
+%%
+
+;;;****************************************************************************
+;;;@ goal
+;;;****************************************************************************
+
+;; simple_stmt are statements that do not involve INDENT tokens
+;; compound_stmt are statements that involve INDENT tokens
+goal
+ : NEWLINE
+ | simple_stmt
+ | compound_stmt
+ ;
+
+;;;****************************************************************************
+;;;@ simple_stmt
+;;;****************************************************************************
+
+;; simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
+simple_stmt
+ : small_stmt_list semicolon_opt NEWLINE
+ ;
+
+;; small_stmt (';' small_stmt)*
+small_stmt_list
+ : small_stmt
+ | small_stmt_list SEMICOLON small_stmt
+ ;
+
+small_stmt
+ : expr_stmt
+ | print_stmt
+ | del_stmt
+ | pass_stmt
+ | flow_stmt
+ | import_stmt
+ | global_stmt
+ | exec_stmt
+ | assert_stmt
+ ;
+
+;;;============================================================================
+;;;@@ print_stmt
+;;;============================================================================
+
+;; print_stmt: 'print' [ test (',' test)* [','] ]
+;; | '>>' test [ (',' test)+ [','] ]
+print_stmt
+ : PRINT print_stmt_trailer
+ (CODE-TAG $1 nil)
+ ;
+
+;; [ test (',' test)* [','] ] | '>>' test [ (',' test)+ [','] ]
+print_stmt_trailer
+ : test_list_opt
+ ()
+ | GTGT test trailing_test_list_with_opt_comma_opt
+ ()
+ ;
+
+;; [ (',' test)+ [','] ]
+trailing_test_list_with_opt_comma_opt
+ : ;;EMPTY
+ | trailing_test_list comma_opt
+ ()
+ ;
+
+;; (',' test)+
+trailing_test_list
+ : COMMA test
+ ()
+ | trailing_test_list COMMA test
+ ()
+ ;
+
+;;;============================================================================
+;;;@@ expr_stmt
+;;;============================================================================
+
+;; expr_stmt: testlist (augassign testlist | ('=' testlist)*)
+expr_stmt
+ : testlist expr_stmt_trailer
+ (if (and $2 (stringp $1) (string-match "^\\(\\sw\\|\\s_\\)+$" $1))
+ ;; If this is an assignment statement and left side is a symbol,
+ ;; then generate a 'variable token, else return 'code token.
+ (VARIABLE-TAG $1 nil nil)
+ (CODE-TAG $1 nil))
+ ;
+
+;; Could be EMPTY because of eq_testlist_zom.
+;; (augassign testlist | ('=' testlist)*)
+expr_stmt_trailer
+ : augassign testlist
+ | eq_testlist_zom
+ ;
+
+;; Could be EMPTY!
+;; ('=' testlist)*
+eq_testlist_zom
+ : ;;EMPTY
+ | eq_testlist_zom ASSIGN testlist
+ (identity $3)
+ ;
+
+;; augassign: '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^='
+;; | '<<=' | '>>=' | '**=' | '//='
+augassign
+ : PLUSEQ | MINUSEQ | MULTEQ | DIVEQ | MODEQ
+ | AMPEQ | OREQ | HATEQ | LTLTEQ
+ | GTGTEQ | EXPEQ | DIVDIVEQ
+ ;
+
+;;;============================================================================
+;;;@@ del_stmt
+;;;============================================================================
+
+;; del_stmt: 'del' exprlist
+del_stmt
+ : DEL exprlist
+ (CODE-TAG $1 nil)
+ ;
+
+;; exprlist: expr (',' expr)* [',']
+exprlist
+ : expr_list comma_opt
+ ()
+ ;
+
+;; expr (',' expr)*
+expr_list
+ : expr
+ ()
+ | expr_list COMMA expr
+ ()
+ ;
+
+;;;============================================================================
+;;;@@ pass_stmt
+;;;============================================================================
+
+;; pass_stmt: 'pass'
+pass_stmt
+ : PASS
+ (CODE-TAG $1 nil)
+ ;
+
+;;;============================================================================
+;;;@@ flow_stmt
+;;;============================================================================
+
+flow_stmt
+ : break_stmt
+ | continue_stmt
+ | return_stmt
+ | raise_stmt
+ | yield_stmt
+ ;
+
+;; break_stmt: 'break'
+break_stmt
+ : BREAK
+ (CODE-TAG $1 nil)
+ ;
+
+;; continue_stmt: 'continue'
+continue_stmt
+ : CONTINUE
+ (CODE-TAG $1 nil)
+ ;
+
+;; return_stmt: 'return' [testlist]
+return_stmt
+ : RETURN testlist_opt
+ (CODE-TAG $1 nil)
+ ;
+
+;; [testlist]
+testlist_opt
+ : ;;EMPTY
+ | testlist
+ ()
+ ;
+
+;; yield_stmt: 'yield' testlist
+yield_stmt
+ : YIELD
+ (CODE-TAG $1 nil)
+ | YIELD testlist
+ (CODE-TAG $1 nil)
+ ;
+
+;; raise_stmt: 'raise' [test [',' test [',' test]]]
+raise_stmt
+ : RAISE zero_one_two_or_three_tests
+ (CODE-TAG $1 nil)
+ ;
+
+;; [test [',' test [',' test]]]
+zero_one_two_or_three_tests
+ : ;;EMPTY
+ | test zero_one_or_two_tests
+ ()
+ ;
+
+;; [',' test [',' test]]
+zero_one_or_two_tests
+ : ;;EMPTY
+ | COMMA test zero_or_one_comma_test
+ ()
+ ;
+
+;; [',' test]
+zero_or_one_comma_test
+ : ;;EMPTY
+ | COMMA test
+ ()
+ ;
+
+;;;============================================================================
+;;;@@ import_stmt
+;;;============================================================================
+
+;; import_stmt : 'import' dotted_as_name (',' dotted_as_name)*
+;; | 'from' dotted_name 'import'
+;; ('*' | import_as_name (',' import_as_name)*)
+import_stmt
+ : IMPORT dotted_as_name_list
+ (INCLUDE-TAG $2 nil)
+ | FROM dotted_name IMPORT star_or_import_as_name_list
+ (INCLUDE-TAG $2 nil)
+ ;
+
+;; dotted_as_name (',' dotted_as_name)*
+dotted_as_name_list
+ : dotted_as_name
+ | dotted_as_name_list COMMA dotted_as_name
+ ;
+
+;; ('*' | import_as_name (',' import_as_name)*)
+star_or_import_as_name_list
+ : MULT
+ ()
+ | import_as_name_list
+ ()
+ ;
+
+;; import_as_name (',' import_as_name)*
+import_as_name_list
+ : import_as_name
+ ()
+ | import_as_name_list COMMA import_as_name
+ ()
+ ;
+
+;; import_as_name: NAME [NAME NAME]
+import_as_name
+ : NAME as_name_opt
+ ()
+ ;
+
+;; dotted_as_name: dotted_name [AS NAME]
+dotted_as_name
+ : dotted_name as_name_opt
+ ;
+
+;; [AS NAME]
+as_name_opt
+ : ;;EMPTY
+ | AS NAME
+ (identity $2)
+ ;
+
+;; dotted_name: NAME ('.' NAME)*
+dotted_name
+ : NAME
+ | dotted_name PERIOD NAME
+ (format "%s.%s" $1 $3)
+ ;
+
+;;;============================================================================
+;;;@@ global_stmt
+;;;============================================================================
+
+;; global_stmt: 'global' NAME (',' NAME)*
+global_stmt
+ : GLOBAL comma_sep_name_list
+ (CODE-TAG $1 nil)
+ ;
+
+;; NAME (',' NAME)*
+comma_sep_name_list
+ : NAME
+ | comma_sep_name_list COMMA NAME
+ ;
+
+;;;============================================================================
+;;;@@ exec_stmt
+;;;============================================================================
+
+;; exec_stmt: 'exec' expr ['in' test [',' test]]
+exec_stmt
+ : EXEC expr exec_trailer
+ (CODE-TAG $1 nil)
+ ;
+
+;; ['in' test [',' test]]
+exec_trailer
+ : ;;EMPTY
+ | IN test comma_test_opt
+ ()
+ ;
+
+;; [',' test]
+comma_test_opt
+ : ;;EMPTY
+ | COMMA test
+ ()
+ ;
+
+;;;============================================================================
+;;;@@ assert_stmt
+;;;============================================================================
+
+;; assert_stmt: 'assert' test [',' test]
+assert_stmt
+ : ASSERT test comma_test_opt
+ (CODE-TAG $1 nil)
+ ;
+
+;;;****************************************************************************
+;;;@ compound_stmt
+;;;****************************************************************************
+
+compound_stmt
+ : if_stmt
+ | while_stmt
+ | for_stmt
+ | try_stmt
+ | funcdef
+ | class_declaration
+ ;
+
+;;;============================================================================
+;;;@@ if_stmt
+;;;============================================================================
+
+;; if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
+if_stmt
+ : IF test COLON suite elif_suite_pair_list else_suite_pair_opt
+ (CODE-TAG $1 nil)
+ ;
+
+;; ('elif' test ':' suite)*
+elif_suite_pair_list
+ : ;;EMPTY
+ | elif_suite_pair_list ELIF test COLON suite
+ ()
+ ;
+
+;; ['else' ':' suite]
+else_suite_pair_opt
+ : ;;EMPTY
+ | ELSE COLON suite
+ ()
+ ;
+
+;; This NT follows the COLON token for most compound statements.
+;; suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT
+suite
+ : simple_stmt
+ (list $1)
+ | NEWLINE indented_block
+ (progn $2)
+ ;
+
+indented_block
+ : INDENT_BLOCK
+ (EXPANDFULL $1 indented_block_body)
+ ;
+
+indented_block_body
+ : INDENT
+ ()
+ | DEDENT
+ ()
+ | simple_stmt
+ | compound_stmt
+ ;
+
+;;;============================================================================
+;;;@@ while_stmt
+;;;============================================================================
+
+;; while_stmt: 'while' test ':' suite ['else' ':' suite]
+while_stmt
+ : WHILE test COLON suite else_suite_pair_opt
+ (CODE-TAG $1 nil)
+ ;
+
+;;;============================================================================
+;;;@@ for_stmt
+;;;============================================================================
+
+;; for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite]
+for_stmt
+ : FOR exprlist IN testlist COLON suite else_suite_pair_opt
+ (CODE-TAG $1 nil)
+ ;
+
+;;;============================================================================
+;;;@@ try_stmt
+;;;============================================================================
+
+;; try_stmt: ('try' ':' suite (except_clause ':' suite)+ #diagram:break
+;; ['else' ':' suite] | 'try' ':' suite 'finally' ':' suite)
+try_stmt
+ : TRY COLON suite except_clause_suite_pair_list else_suite_pair_opt
+ (CODE-TAG $1 nil)
+ | TRY COLON suite FINALLY COLON suite
+ (CODE-TAG $1 nil)
+ ;
+
+;; (except_clause ':' suite)+
+except_clause_suite_pair_list
+ : except_clause COLON suite
+ ()
+ | except_clause_suite_pair_list except_clause COLON suite
+ ()
+ ;
+
+;; # NB compile.c makes sure that the default except clause is last
+;; except_clause: 'except' [test [',' test]]
+except_clause
+ : EXCEPT zero_one_or_two_test
+ ()
+ ;
+
+;; [test [',' test]]
+zero_one_or_two_test
+ : ;;EMPTY
+ | test zero_or_one_comma_test
+ ()
+ ;
+
+;;;============================================================================
+;;;@@ funcdef
+;;;============================================================================
+
+;; funcdef: 'def' NAME parameters ':' suite
+funcdef
+ : DEF NAME function_parameter_list COLON suite
+ (FUNCTION-TAG $2 nil $3)
+ ;
+
+function_parameter_list
+ : PAREN_BLOCK
+ (let ((wisent-python-EXPANDING-block t))
+ (EXPANDFULL $1 function_parameters))
+ ;
+
+;; parameters: '(' [varargslist] ')'
+function_parameters
+ : LPAREN
+ ()
+ | RPAREN
+ ()
+ | function_parameter COMMA
+ | function_parameter RPAREN
+ ;
+
+function_parameter
+ : fpdef_opt_test
+ ;; : NAME
+ ;; (VARIABLE-TAG $1 nil nil)
+ | MULT NAME
+ (VARIABLE-TAG $2 nil nil)
+ | EXPONENT NAME
+ (VARIABLE-TAG $2 nil nil)
+ ;
+
+;;;============================================================================
+;;;@@ class_declaration
+;;;============================================================================
+
+;; classdef: 'class' NAME ['(' testlist ')'] ':' suite
+class_declaration
+ : CLASS NAME paren_class_list_opt COLON suite
+ (TYPE-TAG $2 $1 ;; Name "class"
+ $5 ;; Members
+ (cons $3 nil) ;; (SUPERCLASSES . INTERFACES)
+ )
+ ;
+
+;; ['(' testlist ')']
+paren_class_list_opt
+ : ;;EMPTY
+ | paren_class_list
+ ;
+
+paren_class_list
+ : PAREN_BLOCK
+ (let ((wisent-python-EXPANDING-block t))
+ (mapcar 'semantic-tag-name (EXPANDFULL $1 paren_classes)))
+ ;
+
+;; parameters: '(' [varargslist] ')'
+paren_classes
+ : LPAREN
+ ()
+ | RPAREN
+ ()
+ | paren_class COMMA
+ (VARIABLE-TAG $1 nil nil)
+ | paren_class RPAREN
+ (VARIABLE-TAG $1 nil nil)
+ ;
+
+;; In general, the base class can be specified by a general expression
+;; which evalue to a class object, i.e., base classes are not just names!
+;; However base classes are names in most cases. Thus the
+;; non-terminals below work only with simple names. Even if the
+;; parser can parse general expressions, I don't see much benefit in
+;; generating a string of expression as base class "name".
+paren_class
+ : dotted_name
+ ;
+
+;;;****************************************************************************
+;;;@ test
+;;;****************************************************************************
+
+;; test: and_test ('or' and_test)* | lambdef
+test
+ : test_test
+ | lambdef
+ ;
+
+;; and_test ('or' and_test)*
+test_test
+ : and_test
+ | test_test OR and_test
+ ()
+ ;
+
+;; and_test: not_test ('and' not_test)*
+and_test
+ : not_test
+ | and_test AND not_test
+ ()
+ ;
+
+;; not_test: 'not' not_test | comparison
+not_test
+ : NOT not_test
+ ()
+ | comparison
+ ;
+
+;; comparison: expr (comp_op expr)*
+comparison
+ : expr
+ | comparison comp_op expr
+ ()
+ ;
+
+;; comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'
+comp_op
+ : LT | GT | EQ | GE | LE | LTGT | NE | IN | NOT IN | IS | IS NOT
+ ;
+
+;; expr: xor_expr ('|' xor_expr)*
+expr
+ : xor_expr
+ | expr BAR xor_expr
+ ()
+ ;
+
+;; xor_expr: and_expr ('^' and_expr)*
+xor_expr
+ : and_expr
+ | xor_expr HAT and_expr
+ ()
+ ;
+
+;; and_expr: shift_expr ('&' shift_expr)*
+and_expr
+ : shift_expr
+ | and_expr AMP shift_expr
+ ()
+ ;
+
+;; shift_expr: arith_expr (('<<'|'>>') arith_expr)*
+shift_expr
+ : arith_expr
+ | shift_expr shift_expr_operators arith_expr
+ ()
+ ;
+
+;; ('<<'|'>>')
+shift_expr_operators
+ : LTLT
+ | GTGT
+ ;
+
+;; arith_expr: term (('+'|'-') term)*
+arith_expr
+ : term
+ | arith_expr plus_or_minus term
+ ()
+ ;
+
+;; ('+'|'-')
+plus_or_minus
+ : PLUS
+ | MINUS
+ ;
+
+;; term: factor (('*'|'/'|'%'|'//') factor)*
+term
+ : factor
+ | term term_operator factor
+ ()
+ ;
+
+term_operator
+ : MULT
+ | DIV
+ | MOD
+ | DIVDIV
+ ;
+
+;; factor: ('+'|'-'|'~') factor | power
+factor
+ : prefix_operators factor
+ ()
+ | power
+ ;
+
+;; ('+'|'-'|'~')
+prefix_operators
+ : PLUS
+ | MINUS
+ | TILDE
+ ;
+
+;; power: atom trailer* ('**' factor)*
+power
+ : atom trailer_zom exponent_zom
+ (concat $1
+ (if $2 (concat " " $2 " ") "")
+ (if $3 (concat " " $3) "")
+ )
+ ;
+
+trailer_zom
+ : ;;EMPTY
+ | trailer_zom trailer
+ ()
+ ;
+
+exponent_zom
+ : ;;EMPTY
+ | exponent_zom EXPONENT factor
+ ()
+ ;
+
+;; trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
+trailer
+ : PAREN_BLOCK
+ ()
+ | BRACK_BLOCK
+ ()
+ | PERIOD NAME
+ ()
+ ;
+
+;; atom: '(' [testlist] ')' | '[' [listmaker] ']' | '{' [dictmaker] '}'
+;; | '`' testlist '`' | NAME | NUMBER | STRING+
+atom
+ : PAREN_BLOCK
+ ()
+ | BRACK_BLOCK
+ ()
+ | BRACE_BLOCK
+ ()
+ | BACKQUOTE testlist BACKQUOTE
+ ()
+ | NAME
+ | NUMBER_LITERAL
+ | one_or_more_string
+ ;
+
+test_list_opt
+ : ;;EMPTY
+ | testlist
+ ()
+ ;
+
+;; testlist: test (',' test)* [',']
+testlist
+ : comma_sep_test_list comma_opt
+ ;
+
+;; test (',' test)*
+comma_sep_test_list
+ : test
+ | comma_sep_test_list COMMA test
+ (format "%s, %s" $1 $3)
+ ;
+
+;; (read $1) and (read $2) were done before to peel away the double quotes.
+;; However that does not work for single quotes, so it was taken out.
+one_or_more_string
+ : STRING_LITERAL
+ | one_or_more_string STRING_LITERAL
+ (concat $1 $2)
+ ;
+
+;;;****************************************************************************
+;;;@ lambdef
+;;;****************************************************************************
+
+;; lambdef: 'lambda' [varargslist] ':' test
+lambdef
+ : LAMBDA varargslist_opt COLON test
+ (format "%s %s" $1 (or $2 ""))
+ ;
+
+;; [varargslist]
+varargslist_opt
+ : ;;EMPTY
+ | varargslist
+ ;
+
+;; varargslist: (fpdef ['=' test] ',')* ('*' NAME [',' '**' NAME] | '**' NAME)
+;; | fpdef ['=' test] (',' fpdef ['=' test])* [',']
+varargslist
+ : fpdef_opt_test_list_comma_zom rest_args
+ (nconc $2 $1)
+ | fpdef_opt_test_list comma_opt
+ ;
+
+;; ('*' NAME [',' '**' NAME] | '**' NAME)
+rest_args
+ : MULT NAME multmult_name_opt
+ () ;;(VARIABLE-TAG $2 nil nil)
+ | EXPONENT NAME
+ () ;;(VARIABLE-TAG $2 nil nil)
+ ;
+
+;; [',' '**' NAME]
+multmult_name_opt
+ : ;;EMPTY
+ | COMMA EXPONENT NAME
+ (VARIABLE-TAG $3 nil nil)
+ ;
+
+fpdef_opt_test_list_comma_zom
+ : ;;EMPTY
+ | fpdef_opt_test_list_comma_zom fpdef_opt_test COMMA
+ (nconc $2 $1)
+ ;
+
+;; fpdef ['=' test] (',' fpdef ['=' test])*
+fpdef_opt_test_list
+ : fpdef_opt_test
+ | fpdef_opt_test_list COMMA fpdef_opt_test
+ (nconc $3 $1)
+ ;
+
+;; fpdef ['=' test]
+fpdef_opt_test
+ : fpdef eq_test_opt
+ ;
+
+;; fpdef: NAME | '(' fplist ')'
+fpdef
+ : NAME
+ (VARIABLE-TAG $1 nil nil)
+ ;; Below breaks the parser. Don't know why, but my guess is that
+ ;; LPAREN/RPAREN clashes with the ones in function_parameters.
+ ;; | LPAREN fplist RPAREN
+ ;; (identity $2)
+ ;
+
+;; fplist: fpdef (',' fpdef)* [',']
+fplist
+ : fpdef_list comma_opt
+ ;
+
+;; fpdef (',' fpdef)*
+fpdef_list
+ : fpdef
+ | fpdef_list COMMA fpdef
+ ;
+
+;; ['=' test]
+eq_test_opt
+ : ;;EMPTY
+ | ASSIGN test
+ ()
+ ;
+
+;;;****************************************************************************
+;;;@ Misc
+;;;****************************************************************************
+
+;; [',']
+comma_opt
+ : ;;EMPTY
+ | COMMA
+ ;
+
+;; [';']
+semicolon_opt
+ : ;;EMPTY
+ | SEMICOLON
+ ;
+
+;;; python.wy ends here