Index: mojo/public/bindings/parse/mojo_parser.py |
diff --git a/mojo/public/bindings/parse/mojo_parser.py b/mojo/public/bindings/parse/mojo_parser.py |
index 3e8e991b51f447b9ae8972538881944ddfdbc310..9acaee48f223d46a32adbc8eb09c9a39399950ca 100755 |
--- a/mojo/public/bindings/parse/mojo_parser.py |
+++ b/mojo/public/bindings/parse/mojo_parser.py |
@@ -9,7 +9,6 @@ |
import sys |
import os.path |
- |
# Try to load the ply module, if not, then assume it is in the third_party |
# directory. |
try: |
@@ -26,6 +25,8 @@ except ImportError: |
from ply import lex |
from ply import yacc |
+from mojo_lexer import Lexer |
+ |
def ListFromConcat(*items): |
"""Generate list by concatenating inputs""" |
@@ -41,114 +42,13 @@ def ListFromConcat(*items): |
return itemsout |
-class Lexer(object): |
- |
- # This field is required by lex to specify the complete list of valid tokens. |
- tokens = ( |
- 'NAME', |
- 'NUMBER', |
- |
- 'ORDINAL', |
- |
- 'HANDLE', |
- 'DATAPIPECONSUMER', |
- 'DATAPIPEPRODUCER', |
- 'MESSAGEPIPE', |
- |
- 'MODULE', |
- 'STRUCT', |
- 'INTERFACE', |
- 'ENUM', |
- 'VOID', |
- |
- 'LCURLY', |
- 'RCURLY', |
- 'LPAREN', |
- 'RPAREN', |
- 'LANGLE', |
- 'RANGLE', |
- 'LBRACKET', |
- 'RBRACKET', |
- 'COMMA', |
- 'SEMICOLON', |
- 'EQUALS', |
- ) |
- |
- t_LCURLY = r'{' |
- t_RCURLY = r'}' |
- t_LPAREN = r'\(' |
- t_RPAREN = r'\)' |
- t_LANGLE = r'<' |
- t_RANGLE = r'>' |
- t_LBRACKET = r'\[' |
- t_RBRACKET = r'\]' |
- t_COMMA = r',' |
- t_SEMICOLON = r';' |
- t_EQUALS = r'=' |
- t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*' |
- t_NUMBER = r'\d+' |
- t_ORDINAL = r'@[0-9]*' |
- |
- def t_HANDLE(self, t): |
- r'handle' |
- return t |
- |
- def t_DATAPIPECONSUMER(self, t): |
- r'data_pipe_consumer' |
- return t |
- |
- def t_DATAPIPEPRODUCER(self, t): |
- r'data_pipe_producer' |
- return t |
- |
- def t_MESSAGEPIPE(self, t): |
- r'message_pipe' |
- return t |
- |
- def t_MODULE(self, t): |
- r'module' |
- return t |
- |
- def t_STRUCT(self, t): |
- r'struct' |
- return t |
- |
- def t_INTERFACE(self, t): |
- r'interface' |
- return t |
- |
- def t_ENUM(self, t): |
- r'enum' |
- return t |
- |
- def t_VOID(self, t): |
- r'void' |
- return t |
- |
- # Ignore C and C++ style comments |
- def t_COMMENT(self, t): |
- r'(/\*(.|\n)*?\*/)|(//.*(\n[ \t]*//.*)*)' |
- pass |
- |
- # Ignored characters |
- t_ignore = " \t" |
- |
- def t_newline(self, t): |
- r'\n+' |
- t.lexer.lineno += t.value.count("\n") |
- |
- def t_error(self, t): |
- print("Illegal character '%s'" % t.value[0]) |
- t.lexer.skip(1) |
- |
- |
class Parser(object): |
def __init__(self, lexer): |
self.tokens = lexer.tokens |
def p_module(self, p): |
- """module : MODULE NAME LCURLY definitions RCURLY""" |
+ """module : MODULE NAME LBRACE definitions RBRACE""" |
p[0] = ('MODULE', p[2], p[4]) |
def p_definitions(self, p): |
@@ -179,12 +79,12 @@ class Parser(object): |
p[0] = ListFromConcat(p[1], p[3]) |
def p_attribute(self, p): |
- """attribute : NAME EQUALS NUMBER |
+ """attribute : NAME EQUALS expression |
| NAME EQUALS NAME""" |
p[0] = ('ATTRIBUTE', p[1], p[3]) |
def p_struct(self, p): |
- """struct : attribute_section STRUCT NAME LCURLY struct_body RCURLY SEMICOLON""" |
+ """struct : attribute_section STRUCT NAME LBRACE struct_body RBRACE SEMI""" |
p[0] = ('STRUCT', p[3], p[1], p[5]) |
def p_struct_body(self, p): |
@@ -195,11 +95,11 @@ class Parser(object): |
p[0] = ListFromConcat(p[1], p[2]) |
def p_field(self, p): |
- """field : typename NAME ordinal SEMICOLON""" |
+ """field : typename NAME ordinal SEMI""" |
p[0] = ('FIELD', p[1], p[2], p[3]) |
def p_interface(self, p): |
- """interface : attribute_section INTERFACE NAME LCURLY interface_body RCURLY SEMICOLON""" |
+ """interface : attribute_section INTERFACE NAME LBRACE interface_body RBRACE SEMI""" |
p[0] = ('INTERFACE', p[3], p[1], p[5]) |
def p_interface_body(self, p): |
@@ -210,7 +110,7 @@ class Parser(object): |
p[0] = ListFromConcat(p[1], p[2]) |
def p_method(self, p): |
- """method : VOID NAME LPAREN parameters RPAREN ordinal SEMICOLON""" |
+ """method : VOID NAME LPAREN parameters RPAREN ordinal SEMI""" |
p[0] = ('METHOD', p[2], p[4], p[6]) |
def p_parameters(self, p): |
@@ -240,13 +140,13 @@ class Parser(object): |
p[0] = p[1] |
def p_specializedhandle(self, p): |
- """specializedhandle : HANDLE LANGLE specializedhandlename RANGLE""" |
+ """specializedhandle : HANDLE LT specializedhandlename GT""" |
p[0] = "handle<" + p[3] + ">" |
def p_specializedhandlename(self, p): |
- """specializedhandlename : DATAPIPECONSUMER |
- | DATAPIPEPRODUCER |
- | MESSAGEPIPE""" |
+ """specializedhandlename : DATA_PIPE_CONSUMER |
+ | DATA_PIPE_PRODUCER |
+ | MESSAGE_PIPE""" |
p[0] = p[1] |
def p_array(self, p): |
@@ -260,7 +160,7 @@ class Parser(object): |
p[0] = p[1] |
def p_enum(self, p): |
- """enum : ENUM NAME LCURLY enum_fields RCURLY SEMICOLON""" |
+ """enum : ENUM NAME LBRACE enum_fields RBRACE SEMI""" |
p[0] = ('ENUM', p[2], p[4]) |
def p_enum_fields(self, p): |
@@ -274,12 +174,84 @@ class Parser(object): |
def p_enum_field(self, p): |
"""enum_field : NAME |
- | NAME EQUALS NUMBER""" |
+ | NAME EQUALS expression""" |
if len(p) == 2: |
p[0] = ('ENUM_FIELD', p[1], None) |
else: |
p[0] = ('ENUM_FIELD', p[1], p[3]) |
+ ### Expressions ### |
+ |
+ def p_expression(self, p): |
+ """expression : conditional_expression""" |
+ p[0] = p[1] |
+ |
+ def p_conditional_expression(self, p): |
+ """conditional_expression : binary_expression |
+ | binary_expression CONDOP expression COLON conditional_expression""" |
+ # Just pass the arguments through. I don't think it's possible to preserve |
+ # the spaces of the original, so just put a single space between them. |
+ p[0] = ' '.join(p[1:]) |
+ |
+ # PLY lets us specify precedence of operators, but since we don't actually |
+ # evaluate them, we don't need that here. |
+ def p_binary_expression(self, p): |
+ """binary_expression : unary_expression |
+ | binary_expression binary_operator binary_expression""" |
+ p[0] = ' '.join(p[1:]) |
+ |
+ def p_binary_operator(self, p): |
+ """binary_operator : TIMES |
+ | DIVIDE |
+ | MOD |
+ | PLUS |
+ | MINUS |
+ | RSHIFT |
+ | LSHIFT |
+ | LT |
+ | LE |
+ | GE |
+ | GT |
+ | EQ |
+ | NE |
+ | AND |
+ | OR |
+ | XOR |
+ | LAND |
+ | LOR""" |
+ p[0] = p[1] |
+ |
+ def p_unary_expression(self, p): |
+ """unary_expression : primary_expression |
+ | unary_operator expression""" |
+ p[0] = ''.join(p[1:]) |
+ |
+ def p_unary_operator(self, p): |
+ """unary_operator : TIMES |
+ | PLUS |
+ | MINUS |
+ | NOT |
+ | LNOT""" |
+ p[0] = p[1] |
+ |
+ def p_primary_expression(self, p): |
+ """primary_expression : constant |
+ | NAME |
+ | LPAREN expression RPAREN""" |
+ p[0] = ''.join(p[1:]) |
+ |
+ def p_constant(self, p): |
+ """constant : INT_CONST_DEC |
+ | INT_CONST_OCT |
+ | INT_CONST_HEX |
+ | FLOAT_CONST |
+ | HEX_FLOAT_CONST |
+ | CHAR_CONST |
+ | WCHAR_CONST |
+ | STRING_LITERAL |
+ | WSTRING_LITERAL""" |
+ p[0] = ''.join(p[1:]) |
+ |
def p_error(self, e): |
print('error: %s'%e) |