mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-11-26 07:33:47 +00:00
1204 lines
28 KiB
Plaintext
1204 lines
28 KiB
Plaintext
;;; python.wy -- LALR grammar for Python
|
|
|
|
;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
|
|
;; Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
|
|
;; 2009, 2010 Python Software Foundation; All Rights Reserved
|
|
|
|
;; Author: 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 <https://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
|
|
%provide semantic/wisent/python-wy
|
|
%expectedconflicts 5
|
|
|
|
%{
|
|
(require 'semantic/tag)
|
|
(declare-function wisent-python-reconstitute-function-tag
|
|
"semantic/wisent/python" (tag suite))
|
|
(declare-function wisent-python-reconstitute-class-tag "semantic/wisent/python"
|
|
(tag))
|
|
(declare-function semantic-parse-region "semantic"
|
|
(start end &optional nonterminal depth returnonerror))
|
|
(defvar wisent-python-EXPANDING-block)
|
|
}
|
|
|
|
%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 "`"
|
|
%token <punctuation> AT "@"
|
|
%token <punctuation> FOLLOWS "->"
|
|
|
|
|
|
;; -----------------
|
|
;; 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 WITH "with"
|
|
%put WITH summary
|
|
"Start statement with an associated context object"
|
|
|
|
%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_list COMMA dotted_as_name
|
|
(cons $3 $1)
|
|
| dotted_as_name
|
|
(list $1)
|
|
;
|
|
|
|
;; ('*' | 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
|
|
| with_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
|
|
()
|
|
;
|
|
|
|
;;;============================================================================
|
|
;;@@ with_stmt
|
|
;;;============================================================================
|
|
|
|
;; with_stmt: 'with' test [ with_var ] ':' suite
|
|
with_stmt
|
|
: WITH test COLON suite
|
|
(CODE-TAG $1 nil)
|
|
| WITH test with_var COLON suite
|
|
(CODE-TAG $1 nil) ;; TODO capture variable
|
|
;
|
|
|
|
with_var
|
|
: AS expr
|
|
() ;; TODO capture
|
|
;
|
|
|
|
;;;============================================================================
|
|
;;;@@ funcdef
|
|
;;;============================================================================
|
|
|
|
decorator
|
|
: AT dotted_name varargslist_opt NEWLINE
|
|
(FUNCTION-TAG $2 "decorator" $3)
|
|
;
|
|
|
|
decorators
|
|
: decorator
|
|
(list $1)
|
|
| decorator decorators
|
|
(cons $1 $2)
|
|
;
|
|
|
|
;; funcdef: [decorators] 'def' NAME parameters ':' suite
|
|
funcdef
|
|
: DEF NAME function_parameter_list return_type_hint COLON suite
|
|
(wisent-python-reconstitute-function-tag
|
|
(FUNCTION-TAG $2 nil $3) $6)
|
|
| decorators DEF NAME function_parameter_list return_type_hint COLON suite
|
|
(wisent-python-reconstitute-function-tag
|
|
(FUNCTION-TAG $3 nil $4 :decorators $1) $7)
|
|
;
|
|
|
|
return_type_hint
|
|
: ;;EMPTY
|
|
| FOLLOWS type
|
|
;
|
|
|
|
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
|
|
(wisent-python-reconstitute-class-tag
|
|
(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 evaluates 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
|
|
: type
|
|
;
|
|
|
|
;;;****************************************************************************
|
|
;;;@ 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 type_hint
|
|
(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)
|
|
;
|
|
|
|
;; These rules are now useless because the above rule doesn't refer to them.
|
|
;; ;; fplist: fpdef (',' fpdef)* [',']
|
|
;; fplist
|
|
;; : fpdef_list comma_opt
|
|
;; ;
|
|
|
|
;; ;; fpdef (',' fpdef)*
|
|
;; fpdef_list
|
|
;; : fpdef
|
|
;; | fpdef_list COMMA fpdef
|
|
;; ;
|
|
|
|
type_hint
|
|
: ;;EMPTY
|
|
| COLON type
|
|
;
|
|
|
|
type
|
|
: test
|
|
;
|
|
|
|
;; ['=' test]
|
|
eq_test_opt
|
|
: ;;EMPTY
|
|
| ASSIGN test
|
|
()
|
|
;
|
|
|
|
;;;****************************************************************************
|
|
;;;@ Misc
|
|
;;;****************************************************************************
|
|
|
|
;; [',']
|
|
comma_opt
|
|
: ;;EMPTY
|
|
| COMMA
|
|
;
|
|
|
|
;; [';']
|
|
semicolon_opt
|
|
: ;;EMPTY
|
|
| SEMICOLON
|
|
;
|
|
|
|
;;; python.wy ends here
|