Browse Source

ANTLR grammar converter initial

gm/2021-09-23T00Z/github.com--lark-parser-lark/antlr
Erez Sh 4 years ago
parent
commit
e543dff002
1 changed files with 122 additions and 0 deletions
  1. +122
    -0
      lark/tools/antlr.py

+ 122
- 0
lark/tools/antlr.py View File

@@ -0,0 +1,122 @@
from lark import Lark, Transformer, Discard, v_args

grammar = r"""
start: statement+

?statement: rule
| terminal
| "parser"? "grammar" name ";" -> ignore
| "options" _CODE -> ignore

rule: RULE ":" expansions ";"
terminal: "fragment"? TOKEN ":" term_expansions ";"

?expansions: alias ("|" alias)*

?alias: expansion ["#" name]

?term_expansions: term_alias ("|" term_alias)*
?term_alias: term_expansion ["->" name ["(" name ")"]]
term_expansion: expr*

?expansion: expr*

?expr: atom OP?

?atom: "(" expansions ")"
| value
| _CODE -> ignore
| "~" atom -> not_

?value: name
| STRING -> string
| REGEXP -> regexp

name: RULE
| TOKEN

OP: /[+*][?]?|[?](?![a-z])/
RULE: /[a-z][_a-zA-Z0-9]*/
TOKEN: /[A-Z][_a-zA-Z0-9]*/
REGEXP: /\[.*?\]|\./

_STRING_INNER: /.*?/
_STRING_ESC_INNER: _STRING_INNER /(?<!\\)(\\\\)*?/
STRING : "'" _STRING_ESC_INNER "'"

%import common.INT -> NUMBER
%import common.WS

COMMENT: /\s*/ "//" /[^\n]/*
COMMENT2: /\/\*.*?\*\//s
_CODE: /{.*?}/s

%ignore WS
%ignore COMMENT
%ignore COMMENT2

"""

parser = Lark(grammar, parser='lalr')

class T(Transformer):
def ignore(self, args):
raise Discard()

def expansions(self, x):
return '\n | '.join(x)

def term_expansions(self, x):
return '\n | '.join(x)

def term_alias(self, x):
# TODO channel hidden -> ignore
return x[0]

def expansion(self, x):
return "(" + ' '.join(x) + ")"

def term_expansion(self, x):
return "(" + ' '.join(x) + ")"

@v_args(inline=True)
def expr(self, expr, op):
return expr + op.value

@v_args(inline=True)
def rule(self, name, exprs):
return name + ": " + exprs

@v_args(inline=True)
def terminal(self, name, exprs):
if not isinstance(exprs, str):
breakpoint()
return name + ": " + exprs

@v_args(inline=True)
def name(self, t):
return t.value

@v_args(inline=True)
def string(self, t):
return t.value.replace('\\', '\\\\').replace('"', '\\"').replace("'", '"')

@v_args(inline=True)
def regexp(self, t):
return f'/{t.value}/'

@v_args(inline=True)
def not_(self, t):
return f" /(?!){t}/ "

def start(self, stmts):
return '\n\n'.join(stmts)


with open('SQLite.g4') as f:
res = parser.parse(f.read())
# print('###', res.pretty())
res = T().transform(res)

with open('sqlite.lark', 'w') as f:
f.write(res)

Loading…
Cancel
Save