An example based on a language I once knew
This commit is contained in:
parent
0af5cfe2ee
commit
0ddf166e4e
1 changed files with 233 additions and 0 deletions
233
examples/lens.py
Normal file
233
examples/lens.py
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
from parser import *
|
||||
|
||||
|
||||
@rule
|
||||
def expression():
|
||||
return alt(
|
||||
TRUE | FALSE | NUMBER | NAME,
|
||||
LPAREN + expression + RPAREN,
|
||||
binary_expression,
|
||||
object_expression,
|
||||
with_expression,
|
||||
function_expression,
|
||||
invoke_expression,
|
||||
member_expression,
|
||||
statement_block_expression,
|
||||
)
|
||||
|
||||
|
||||
@rule
|
||||
def binary_expression():
|
||||
return alt(
|
||||
expression + PLUS + expression,
|
||||
expression + STAR + expression,
|
||||
expression + MINUS + expression,
|
||||
expression + SLASH + expression,
|
||||
expression + LESSER + expression,
|
||||
expression + GREATER + expression,
|
||||
expression + LESSER_EQUAL + expression,
|
||||
expression + GREATER_EQUAL + expression,
|
||||
expression + EQUAL_EQUAL + expression,
|
||||
expression + AND + expression,
|
||||
expression + OR + expression,
|
||||
)
|
||||
|
||||
|
||||
@rule
|
||||
def object_expression():
|
||||
return LCURLY + zero_or_more(value_pair + opt(COMMA)) + RCURLY
|
||||
|
||||
|
||||
@rule
|
||||
def value_pair():
|
||||
return value_name + opt(EQUAL, expression)
|
||||
|
||||
|
||||
@rule
|
||||
def value_name():
|
||||
return NAME | LSQUARE + expression + RSQUARE
|
||||
|
||||
|
||||
@rule
|
||||
def with_expression():
|
||||
return WITH + object_expression + YIELD + expression
|
||||
|
||||
|
||||
@rule
|
||||
def function_expression():
|
||||
return FN + opt(param_list) + FAT_ARROW + expression
|
||||
|
||||
|
||||
@rule
|
||||
def param_list():
|
||||
return zero_or_more(NAME + COMMA) + NAME + opt(COMMA)
|
||||
|
||||
|
||||
@rule
|
||||
def invoke_expression():
|
||||
return seq(
|
||||
expression,
|
||||
LPAREN,
|
||||
opt(
|
||||
zero_or_more(expression + COMMA),
|
||||
expression + opt(COMMA),
|
||||
),
|
||||
RPAREN,
|
||||
)
|
||||
|
||||
|
||||
@rule
|
||||
def member_expression():
|
||||
return expression + DOT + NAME
|
||||
|
||||
|
||||
@rule
|
||||
def statement_block_expression():
|
||||
return DO + statement_list + YIELD + expression
|
||||
|
||||
|
||||
@rule
|
||||
def statement_list():
|
||||
return zero_or_more(_statement)
|
||||
|
||||
|
||||
@rule
|
||||
def _statement():
|
||||
return alt(
|
||||
assignment_statement,
|
||||
if_statement,
|
||||
declaration_statement,
|
||||
while_loop,
|
||||
)
|
||||
|
||||
|
||||
@rule
|
||||
def assignment_statement():
|
||||
return (
|
||||
NAME
|
||||
+ alt(COLON_EQUAL, PLUS_EQUAL, MINUS_EQUAL, STAR_EQUAL, SLASH_EQUAL)
|
||||
+ expression
|
||||
+ SEMICOLON
|
||||
)
|
||||
|
||||
|
||||
@rule
|
||||
def if_statement():
|
||||
return IF + expression + THEN + statement_list + END
|
||||
|
||||
|
||||
@rule
|
||||
def declaration_statement():
|
||||
return VAR + NAME + COLON_EQUAL + expression + SEMICOLON
|
||||
|
||||
|
||||
@rule
|
||||
def while_loop():
|
||||
return WHILE + expression + DO + statement_list + END
|
||||
|
||||
|
||||
BLANKS = Terminal("BLANKS", Re.set(" ", "\t", "\r", "\n").plus())
|
||||
COMMENT = Terminal("COMMENT", Re.seq(Re.literal("//"), Re.set("\n").invert().star()))
|
||||
|
||||
TRUE = Terminal("TRUE", "true")
|
||||
FALSE = Terminal("FALSE", "false")
|
||||
|
||||
NUMBER = Terminal(
|
||||
"NUMBER",
|
||||
Re.seq(
|
||||
Re.set(("0", "9")).plus(),
|
||||
Re.seq(
|
||||
Re.literal("."),
|
||||
Re.set(("0", "9")).plus(),
|
||||
).question(),
|
||||
Re.seq(
|
||||
Re.set("e", "E"),
|
||||
Re.set("+", "-").question(),
|
||||
Re.set(("0", "9")).plus(),
|
||||
).question(),
|
||||
),
|
||||
highlight=highlight.constant.numeric,
|
||||
)
|
||||
|
||||
FN = Terminal("FN", "fn")
|
||||
ARROW = Terminal("ARROW", "->")
|
||||
FAT_ARROW = Terminal("FAT_ARROW", "=>")
|
||||
|
||||
COMMA = Terminal("COMMA", ",")
|
||||
LPAREN = Terminal("LPAREN", "(")
|
||||
RPAREN = Terminal("RPAREN", ")")
|
||||
LCURLY = Terminal("LCURLY", "{")
|
||||
RCURLY = Terminal("RCURLY", "}")
|
||||
LSQUARE = Terminal("LSQUARE", "[")
|
||||
RSQUARE = Terminal("RSQUARE", "]")
|
||||
COLON = Terminal("COLON", ":")
|
||||
SEMICOLON = Terminal("SEMICOLON", ";")
|
||||
LET = Terminal("LET", "let")
|
||||
EQUAL = Terminal("EQUAL", "=")
|
||||
RETURN = Terminal("RETURN", "return")
|
||||
PLUS = Terminal("PLUS", "+")
|
||||
PLUS_EQUAL = Terminal("PLUS_EQUAL", "+=")
|
||||
MINUS = Terminal("MINUS", "-")
|
||||
MINUS_EQUAL = Terminal("MINUS_EQUAL", "-=")
|
||||
STAR = Terminal("STAR", "*")
|
||||
STAR_EQUAL = Terminal("STAR_EQUAL", "*=")
|
||||
SLASH = Terminal("SLASH", "/")
|
||||
SLASH_EQUAL = Terminal("SLASH_EQUAL", "/=")
|
||||
DOT = Terminal("DOT", ".")
|
||||
|
||||
# Design: A different assignment operator to make sure we
|
||||
# don't get confused.
|
||||
COLON_EQUAL = Terminal("COLON_EQUAL", ":=")
|
||||
|
||||
GREATER = Terminal("GREATER", ">")
|
||||
GREATER_EQUAL = Terminal("GREATER_EQUAL", ">=")
|
||||
LESSER = Terminal("LESSER", "<")
|
||||
LESSER_EQUAL = Terminal("LESSER_EQUAL", "<=")
|
||||
EQUAL_EQUAL = Terminal("EQUAL_EQUAL", "==")
|
||||
AND = Terminal("AND", "and")
|
||||
OR = Terminal("OR", "or")
|
||||
NOT = Terminal("NOT", "not")
|
||||
|
||||
# I like `DO -> YIELD` instead of `BEGIN -> YIELD`
|
||||
# A `YIELD` at the end instead of a generic "last expression"
|
||||
# setup because I want to be explicit that blocks yield values
|
||||
# and you don't get the wrong one by accident!
|
||||
DO = Terminal("DO", "do")
|
||||
IF = Terminal("IF", "if")
|
||||
THEN = Terminal("THEN", "then")
|
||||
END = Terminal("END", "end")
|
||||
WHILE = Terminal("WHILE", "while")
|
||||
|
||||
# I just like explicit variable declaration, otherwise
|
||||
# sometimes you don't mean to make a new variable but
|
||||
# make a typeo and do. :(
|
||||
#
|
||||
# This also allows you to control shadowing.
|
||||
VAR = Terminal("VAR", "var")
|
||||
|
||||
|
||||
WITH = Terminal("WITH", "with")
|
||||
YIELD = Terminal("YIELD", "yield")
|
||||
|
||||
NAME = Terminal(
|
||||
"NAME",
|
||||
Re.seq(
|
||||
Re.set(("a", "z"), ("A", "Z"), "_"),
|
||||
Re.set(("a", "z"), ("A", "Z"), ("0", "9"), "_").star(),
|
||||
),
|
||||
)
|
||||
|
||||
LensGrammar = Grammar(
|
||||
name="Lens",
|
||||
start=expression,
|
||||
trivia=[BLANKS, COMMENT],
|
||||
precedence=[
|
||||
(Assoc.LEFT, [OR]),
|
||||
(Assoc.LEFT, [AND]),
|
||||
(Assoc.LEFT, [EQUAL_EQUAL, LESSER_EQUAL, LESSER, GREATER_EQUAL, GREATER]),
|
||||
(Assoc.LEFT, [PLUS, MINUS]),
|
||||
(Assoc.LEFT, [STAR, SLASH]),
|
||||
(Assoc.LEFT, [LPAREN]),
|
||||
(Assoc.LEFT, [DOT]),
|
||||
],
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue