Files
uwrap/lang_template/language/parser.py
2022-05-19 16:41:48 +02:00

406 lines
10 KiB
Python

from langkit.dsl import ASTNode, abstract, Field
from langkit.parsers import Grammar, List, Pick, Or, Opt, Null
from language.lexer import *
@abstract
class TemplateNode(ASTNode):
"""
Root node class for Wraplang AST nodes.
"""
pass
class Import(TemplateNode):
name = Field()
class Module(TemplateNode):
import_clauses = Field()
program = Field()
class Template(TemplateNode):
name = Field()
extending = Field()
command = Field()
class Var(TemplateNode):
name = Field()
typ = Field()
args = Field()
init = Field()
class Command(TemplateNode):
actions = Field()
class DeferSection (TemplateNode):
expression = Field()
actions = Field ()
class MatchSection(TemplateNode):
expression = Field()
actions = Field ()
class PickSection (TemplateNode):
expression = Field ()
actions = Field ()
@abstract
class TemplateSection(TemplateNode):
actions = Field(type=TemplateNode)
class WrapSection(TemplateSection):
pass
class WeaveSection(TemplateSection):
pass
class WalkSection(TemplateSection):
pass
class TemplateCall(TemplateNode):
captured = Field()
name = Field()
args = Field()
class MatchCapture(TemplateNode):
captured = Field()
expression = Field()
@abstract
class Expr(TemplateNode):
pass
class Number(Expr):
token_node = True
class Identifier(Expr):
token_node = True
class Literal (Expr):
token_node = True
class Str(Expr):
token_node = True
class Operator(TemplateNode):
enum_node = True
alternatives = [
'and',
'or',
'not',
'amp',
'is',
'has',
'many',
'few',
'plus',
'minus',
'multiply',
'divide',
'eq',
'neq',
'lt',
'gt',
'lte',
'gte']
class BinaryExpr(Expr):
lhs = Field()
op = Field()
rhs = Field()
class UnaryExpr(Expr):
op = Field()
rhs = Field()
class Function(Expr):
name = Field()
args = Field()
program = Field()
class MatchExpr (Expr):
match_exp = Field ()
pick_exp = Field ()
else_exp = Field ()
class CallExpr (TemplateNode):
called = Field()
args = Field()
class DeferExpr (TemplateNode):
expression = Field()
class Argument(TemplateNode):
name = Field()
value = Field()
class Selector(TemplateNode):
left=Field()
right=Field()
class TraverseInto (TemplateNode):
pass
class TraverseOver (TemplateNode):
pass
class NewExpr(TemplateNode):
tree=Field()
class FoldExpr(TemplateNode):
default=Field()
combine=Field()
separator=Field()
class FilterExpr(TemplateNode):
expression=Field()
class AllExpr(TemplateNode):
expression=Field()
class AtRef (TemplateNode):
token_node = True
class CreateTemplateTree (TemplateNode):
root=Field()
tree=Field()
class QualifiedMatch (TemplateNode):
op = Field()
rhs = Field()
class CommandSequence (TemplateNode):
sequence = Field()
class CommandSequenceElement (TemplateNode):
vars = Field()
commands = Field()
next = Field(type=TemplateNode)
class ThenSequence (TemplateNode):
actions = Field()
class ElsmatchSequence (TemplateNode):
expression = Field()
actions = Field()
class ElseSequence (TemplateNode):
actions = Field()
class RegExpr (TemplateNode):
captured = Field ()
left = Field(type=TemplateNode)
right = Field(type=TemplateNode)
class RegExprAnchor (TemplateNode):
token_node = True
class RegExprQuantifier (TemplateNode):
quantifier = Field ()
expr = Field ()
min = Field ()
max = Field ()
template_grammar = Grammar('main_rule')
G = template_grammar
template_grammar.add_rules(
main_rule=Module (List (G.import_clause, empty_valid=True), G.module_scope),
import_clause=Import('import', G.dotted_name, ';'),
module_scope=List(Or (G.template, G.command, G.function, G.var), empty_valid=True),
template=Template('template', G.identifier, Opt ('extends', G.dotted_name), Or (G.command, Pick (Null (G.command), ';'))),
var=Var('var', G.identifier, ':', G.identifier, Opt ('(', G.arg_list, ')'), Opt ('=>', G.expression), ';'),
command=Command(
Or(
G.defer_section,
G.match_section,
G.pick_section,
G.wrap_section,
G.weave_section,
G.walk_section,
G.command_sequence
)
),
defer_section=DeferSection (
'defer', Opt (G.expression),
Or(
G.match_section,
G.pick_section,
G.wrap_section,
G.weave_section,
G.walk_section,
G.command_sequence
)
),
match_section=MatchSection (
Pick ('match', G.expression),
Or (
G.pick_section,
G.wrap_section,
G.weave_section,
G.walk_section,
G.conditionned_command_sequence,
Pick (Null (G.command_sequence), ';'))
),
pick_section=PickSection (
Pick ('pick', G.expression),
Or (
G.wrap_section,
G.weave_section,
G.walk_section,
G.command_sequence,
Pick (Null (G.command_sequence), ';'))
),
weave_section=WeaveSection(
'weave',
Or (
G.template_call,
TemplateCall(Null (G.identifier), Null (G.dotted_name), '(', G.arg_list, ')'),
G.traverse_decision),
';'),
wrap_section=WrapSection(
'wrap',
Or (
G.template_call,
G.traverse_decision),
';'),
walk_section=WalkSection('walk', G.template_call, ';'),
command_sequence=CommandSequence ('do', G.command_sequence_element, 'end', ';'),
command_sequence_element=CommandSequenceElement (
List (G.var, empty_valid = True),
List (G.command, empty_valid = True),
Opt (ThenSequence ('then', G.command_sequence_element))
),
conditionned_command_sequence=CommandSequence ('do', G.conditionned_command_sequence_element, 'end', ';'),
conditionned_command_sequence_element=CommandSequenceElement (
List (G.var, empty_valid = True),
List (G.command, empty_valid = True),
Opt (Or (
ThenSequence ('then', G.conditionned_command_sequence_element),
ElsmatchSequence ('elsmatch', G.expression, 'do', G.conditionned_command_sequence_element),
ElseSequence ('else', G.command_sequence_element)))
),
traverse_decision=Or(TraverseInto ('into'), TraverseOver ('over')),
function=Function('function', G.identifier, '(', Opt (List (G.identifier, sep = ',', empty_valid = True)), ')', G.command_sequence),
root_expression=Or (
RegExpr (
Null (G.identifier),
RegExprAnchor ('\\'),
G.regular_expression),
G.regular_expression),
regular_expression=Or(
RegExpr (
Opt (Pick (G.identifier, ':')),
Or (
Pick ('(', G.regular_expression_no_terminal, ')'),
G.regular_expression_quantifier,
),
Opt (Or (Pick ('\\', G.regular_expression), RegExprAnchor ('\\'))),
),
RegExpr (
Null (G.identifier),
G.expression,
Or (Pick ('\\', G.regular_expression), RegExprAnchor ('\\')),
),
G.expression
),
regular_expression_no_terminal=Or(
RegExpr (
Opt (Pick (G.identifier, ':')),
Or (
Pick ('(', G.regular_expression_no_terminal, ')'),
G.regular_expression_quantifier
),
Opt (Pick ('\\', Or (G.regular_expression_no_terminal, G.expression))),
),
RegExpr (
Null (G.identifier),
G.expression,
Pick ('\\', Or (G.regular_expression_no_terminal, G.expression)),
),
),
regular_expression_quantifier=RegExprQuantifier (
Or (Operator.alt_many('many'), Operator.alt_few('few')),
'(',
Or (G.regular_expression_no_terminal, G.expression),
Opt (Pick (',', G.integer)),
Opt (Pick (',', G.integer)),
')'),
expression=Or (
BinaryExpr (G.relation, Or (Operator.alt_and('and'), Operator.alt_or('or')), G.expression),
G.relation),
relation=Or (
BinaryExpr (G.simple_expression, Or (
Operator.alt_eq('='),
Operator.alt_neq('/='),
Operator.alt_lt('<'),
Operator.alt_gt('>'),
Operator.alt_lte('<='),
Operator.alt_gte('>=')), G.simple_expression),
G.simple_expression),
simple_expression=Or (BinaryExpr (G.term, Or (Operator.alt_amp('&'), Operator.alt_minus('-'), Operator.alt_plus('+')), G.simple_expression), G.term),
term=Or (BinaryExpr (G.factor, Or (Operator.alt_multiply('*'), Operator.alt_divide('/')), G.term), G.factor),
factor=Or(
MatchCapture(G.identifier, ':', G.factor),
UnaryExpr (Operator.alt_not('not'), G.qualified_primary),
G.qualified_primary),
qualified_primary=Or (QualifiedMatch (Or (Operator.alt_is('is'), Operator.alt_has ('has')), '(', G.expression, ')'), G.primary),
primary=Or(
Pick ('(', G.expression, ')'),
G.match_expr,
G.defer_expr,
G.literal,
G.integer,
G.str,
G.selected_component,
G.name
),
match_expr=Pick ('(', G.match_expr_element, ')'),
match_expr_element=MatchExpr (
'match', G.expression, 'pick', G.expression,
Opt ('else', Or (
Pick ('pick', G.expression),
G.match_expr_element))),
name=Or(
G.single_name
),
single_name=Or (
G.at_ref,
G.new_expr,
G.fold_expr,
G.filter_expr,
G.all_expr,
G.call_expr,
G.identifier),
selected_component=Selector (G.prefix, '.', G.suffix),
prefix=Or (
G.name
),
suffix=Or (
G.selected_component,
G.name
),
new_expr=NewExpr ('new', '(', G.create_template_tree, ')'),
template_call=TemplateCall(Opt (G.identifier, ':'), G.dotted_name, '(', G.arg_list, ')'),
create_template_tree=Or(
CreateTemplateTree(G.template_call, Opt ('{', List (G.create_template_tree, sep = ',', empty_valid = True), '}')),
CreateTemplateTree(Null (G.template_call), '{', List (G.create_template_tree, sep = ',', empty_valid = True), '}')),
fold_expr=FoldExpr ('fold', '(', G.expression, ',', G.expression, Opt (',', G.expression), ')'),
filter_expr=FilterExpr ('filter', '(', G.root_expression, ')'),
all_expr=AllExpr ('all', '(', Opt (G.expression), ')'),
at_ref=AtRef('@'),
call_expr=CallExpr (G.identifier, '(', G.arg_list, ')'),
defer_expr=DeferExpr ('defer', '(', G.expression, ')'),
arg_list=List(Argument(Opt (G.identifier, "=>"), G.root_expression), sep=',', empty_valid=True),
identifier=Identifier(Token.Identifier),
dotted_name=Selector(Opt (G.dotted_name, '.'), G.identifier),
integer=Number(Token.Integer),
literal=Literal(Or ("true", "false")),
str=Str(Token.String)
)