ソースを参照

Examples: Added example of extending the Python grammar

tags/gm/2021-09-23T00Z/github.com--lark-parser-lark/0.11.2
Erez Sh 3年前
コミット
8cfe52fb77
3個のファイルの変更49行の追加59行の削除
  1. +46
    -0
      examples/advanced/extend_python.py
  2. +0
    -59
      examples/advanced/grammar_building.py
  3. +3
    -0
      lark/load_grammar.py

+ 46
- 0
examples/advanced/extend_python.py ファイルの表示

@@ -0,0 +1,46 @@
"""
Extend the Python Grammar
==============================

This example demonstrates how to use the `%extend` statement,
to add new syntax to the example Python grammar.

"""

from lark.lark import Lark
from python_parser import PythonIndenter

GRAMMAR = r"""
%import .python3 (compound_stmt, single_input, file_input, eval_input, test, suite, _NEWLINE, _INDENT, _DEDENT, COMMENT)

%extend compound_stmt: match_stmt

match_stmt: "match" test ":" cases
cases: _NEWLINE _INDENT case+ _DEDENT

case: "case" test ":" suite // test is not quite correct.

%ignore /[\t \f]+/ // WS
%ignore /\\[\t \f]*\r?\n/ // LINE_CONT
%ignore COMMENT
"""

parser = Lark(GRAMMAR, parser='lalr', start=['single_input', 'file_input', 'eval_input'], postlex=PythonIndenter())

tree = parser.parse(r"""
def name(n):
match n:
case 1:
print("one")
case 2:
print("two")
case _:
print("number is too big")

""", start='file_input')

# Remove the 'python3__' prefix that was add to the implicitely imported rules.
for t in tree.iter_subtrees():
t.data = t.data.rsplit('__', 1)[-1]

print(tree.pretty())

+ 0
- 59
examples/advanced/grammar_building.py ファイルの表示

@@ -1,59 +0,0 @@
from pathlib import Path

from lark.indenter import Indenter
from lark.lark import Lark
from lark.load_grammar import GrammarBuilder

MATCH_GRAMMAR = ('match', """

%extend compound_stmt: match_stmt

match_stmt: "match" test ":" cases

cases: _NEWLINE _INDENT case+ _DEDENT

case: "case" test ":" suite // test is not quite correct.

""", ('compound_stmt', 'test', 'suite', '_DEDENT', '_INDENT', '_NEWLINE'))

EXTENSIONS = (MATCH_GRAMMAR,)

builder = GrammarBuilder()

builder.load_grammar((Path(__file__).with_name('python3.lark')).read_text(), 'python3')

for name, ext_grammar, needed_names in EXTENSIONS:
mangle = builder.get_mangle(name, dict(zip(needed_names, needed_names)))
builder.load_grammar(ext_grammar, name, mangle)

grammar = builder.build()


class PythonIndenter(Indenter):
NL_type = '_NEWLINE'
OPEN_PAREN_types = ['LPAR', 'LSQB', 'LBRACE']
CLOSE_PAREN_types = ['RPAR', 'RSQB', 'RBRACE']
INDENT_type = '_INDENT'
DEDENT_type = '_DEDENT'
tab_len = 8


parser = Lark(grammar, parser='lalr', start=['single_input', 'file_input', 'eval_input'], postlex=PythonIndenter())

tree = parser.parse(r"""

a = 5

def name(n):
match n:
case 1:
print("one")
case 2:
print("two")
case _:
print("number is to big")

name(a)
""", start='file_input')

print(tree.pretty())

+ 3
- 0
lark/load_grammar.py ファイルの表示

@@ -977,6 +977,9 @@ class GrammarBuilder:
aliases = dict(zip(names, names)) # Can't have aliased multi import, so all aliases will be the same as names
else: # Single import
dotted_path = tuple(path_node.children[:-1])
if not dotted_path:
name ,= path_node.children
raise GrammarError("Nothing was imported from grammar `%s`" % name)
name = path_node.children[-1] # Get name from dotted path
aliases = {name.value: (arg1 or name).value} # Aliases if exist



読み込み中…
キャンセル
保存