Skip to content

Instantly share code, notes, and snippets.

@soasme
Last active January 23, 2017 08:13
Show Gist options
  • Save soasme/afb0f5e08a4fc6119523ccc92b1739fe to your computer and use it in GitHub Desktop.
Save soasme/afb0f5e08a4fc6119523ccc92b1739fe to your computer and use it in GitHub Desktop.
# -*- coding: utf-8 -*-
GRAMMAR = r"""
IGNORE: "[ \t\n]";
UNARY_OP: "[+-!]";
IDENTIFIER: "[a-zA-Z_][a-zA-Z0-9_]*";
STRING_LITERAL: "\\"[^\\\\"]*\\"";
DECIMAL_LITERAL: "0|[1-9][0-9]*";
OCTAL_LITERAL: "0[oO][0-7]+";
HEX_LITERAL: "0[xX][0-9a-fA-F]+";
BIN_LITERAL: "0[bB][0-1]+";
FLOAT_LITERAL: "\-?(0|[1-9][0-9]*)(\.[0-9]+)([eE][\+\-]?[0-9]+)?";
PASS: "pass";
main: (import [";"])* (export [";"])? statement* [EOF];
import: import_module | import_members_from_module;
import_module: "import" STRING_LITERAL;
import_members_from_module: "import" import_members "from" STRING_LITERAL;
import_members: (IDENTIFIER ",")* IDENTIFIER;
export: export_all_members | export_selected_members;
export_all_members: "export" "*" "as" IDENTIFIER;
export_selected_members: "export" (IDENTIFIER ",")* IDENTIFIER "as" IDENTIFIER;
statement: compound_statement | simple_statement [";"];
compound_statement: block | if | do | def;
simple_statement: PASS | abort | return | assignment | expression ;
block: "{" statement* "}";
guardcommand: "(" expression ")" block;
if: "if" guardcommand+;
do: "do" guardcommand+;
def: "def" IDENTIFIER "(" args? ")" block;
return: "return" expression;
abort: "abort" expression;
assignment: IDENTIFIER selector* ["="] expression;
expression: primary_expression binary_op expression | unary_expression;
unary_expression: UNARY_OP unary_expression | primary_expression;
primary_expression: atom primary_expression_rest*;
primary_expression_rest: selector | arguments;
selector: <identifier_selector> | <index_selector>;
identifier_selector: ["."] IDENTIFIER;
index_selector: ["["] expression ["]"];
expressions: expression ([","] <expression>)*;
arguments: ["("] (expressions ","?)? [")"];
array_literal: "[" array_elements? "]";
array_elements: expression ([","] expression)* ","?;
object_literal: "{" object_entries? "}";
object_entries: object_entry ([","] object_entry)* ","?;
object_entry: object_identifier_entry | object_string_entry;
object_identifier_entry: IDENTIFIER ":" object_entry_value;
object_string_entry: STRING_LITERAL ":" object_entry_value;
object_entry_value: closure | expression;
closure: "def" ["("] args [")"] block;
args: IDENTIFIER [","] args | IDENTIFIER;
# operand_name: IDENTIFIER | qualified_identifier;
# qualified_identifier: package_name "." IDENTIFIER;
# package_name: IDENTIFIER;
binary_op: "||" | "&&" | "==" | "!=" | "<" | "<=" | ">" | ">=" | "+" | "-" | "|" | "^" | "*" | "/" | "%" | "<<" | ">>" | "&" | "&^";
atom: literal | IDENTIFIER | array_literal | object_literal | parenthesized_form;
parenthesized_form: ["("] <expression> [")"];
integer_literal: DECIMAL_LITERAL | OCTAL_LITERAL | HEX_LITERAL | BIN_LITERAL;
literal: "true" | "false" | integer_literal | FLOAT_LITERAL | STRING_LITERAL;
"""
from rpython.rlib.parsing.ebnfparse import parse_ebnf, make_parse_function
from rpython.rlib.parsing.parsing import ParseError
from rpython.rlib.parsing.deterministic import LexerError
from rpython.rlib.parsing.tree import RPythonVisitor
if __name__ == '__main__':
import sys
with open(sys.argv[1]) as f:
source = f.read()
regexs, rules, ToAST = parse_ebnf(GRAMMAR)
_parse = make_parse_function(regexs, rules, eof=True)
try:
tree = _parse(source)
print tree
except ParseError as e:
print(e.nice_error_message(sys.argv[1], source))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment