Chromium Code Reviews| 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..80d0a121684dbd985ba3ee6f23ae1de5490830d3 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 |
|
darin (slow to review)
2014/01/10 00:36:34
Perhaps we should evaluate these expressions here?
|
| + # 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) |