Index: trunk/src/mojo/public/bindings/parse/mojo_parser.py |
=================================================================== |
--- trunk/src/mojo/public/bindings/parse/mojo_parser.py (revision 244236) |
+++ trunk/src/mojo/public/bindings/parse/mojo_parser.py (working copy) |
@@ -9,6 +9,7 @@ |
import sys |
import os.path |
+ |
# Try to load the ply module, if not, then assume it is in the third_party |
# directory. |
try: |
@@ -25,9 +26,7 @@ |
from ply import lex |
from ply import yacc |
-from mojo_lexer import Lexer |
- |
def ListFromConcat(*items): |
"""Generate list by concatenating inputs""" |
itemsout = [] |
@@ -42,13 +41,114 @@ |
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 LBRACE definitions RBRACE""" |
+ """module : MODULE NAME LCURLY definitions RCURLY""" |
p[0] = ('MODULE', p[2], p[4]) |
def p_definitions(self, p): |
@@ -79,12 +179,12 @@ |
p[0] = ListFromConcat(p[1], p[3]) |
def p_attribute(self, p): |
- """attribute : NAME EQUALS expression |
+ """attribute : NAME EQUALS NUMBER |
| NAME EQUALS NAME""" |
p[0] = ('ATTRIBUTE', p[1], p[3]) |
def p_struct(self, p): |
- """struct : attribute_section STRUCT NAME LBRACE struct_body RBRACE SEMI""" |
+ """struct : attribute_section STRUCT NAME LCURLY struct_body RCURLY SEMICOLON""" |
p[0] = ('STRUCT', p[3], p[1], p[5]) |
def p_struct_body(self, p): |
@@ -95,11 +195,11 @@ |
p[0] = ListFromConcat(p[1], p[2]) |
def p_field(self, p): |
- """field : typename NAME ordinal SEMI""" |
+ """field : typename NAME ordinal SEMICOLON""" |
p[0] = ('FIELD', p[1], p[2], p[3]) |
def p_interface(self, p): |
- """interface : attribute_section INTERFACE NAME LBRACE interface_body RBRACE SEMI""" |
+ """interface : attribute_section INTERFACE NAME LCURLY interface_body RCURLY SEMICOLON""" |
p[0] = ('INTERFACE', p[3], p[1], p[5]) |
def p_interface_body(self, p): |
@@ -110,7 +210,7 @@ |
p[0] = ListFromConcat(p[1], p[2]) |
def p_method(self, p): |
- """method : VOID NAME LPAREN parameters RPAREN ordinal SEMI""" |
+ """method : VOID NAME LPAREN parameters RPAREN ordinal SEMICOLON""" |
p[0] = ('METHOD', p[2], p[4], p[6]) |
def p_parameters(self, p): |
@@ -140,13 +240,13 @@ |
p[0] = p[1] |
def p_specializedhandle(self, p): |
- """specializedhandle : HANDLE LT specializedhandlename GT""" |
+ """specializedhandle : HANDLE LANGLE specializedhandlename RANGLE""" |
p[0] = "handle<" + p[3] + ">" |
def p_specializedhandlename(self, p): |
- """specializedhandlename : DATA_PIPE_CONSUMER |
- | DATA_PIPE_PRODUCER |
- | MESSAGE_PIPE""" |
+ """specializedhandlename : DATAPIPECONSUMER |
+ | DATAPIPEPRODUCER |
+ | MESSAGEPIPE""" |
p[0] = p[1] |
def p_array(self, p): |
@@ -160,7 +260,7 @@ |
p[0] = p[1] |
def p_enum(self, p): |
- """enum : ENUM NAME LBRACE enum_fields RBRACE SEMI""" |
+ """enum : ENUM NAME LCURLY enum_fields RCURLY SEMICOLON""" |
p[0] = ('ENUM', p[2], p[4]) |
def p_enum_fields(self, p): |
@@ -174,84 +274,12 @@ |
def p_enum_field(self, p): |
"""enum_field : NAME |
- | NAME EQUALS expression""" |
+ | NAME EQUALS NUMBER""" |
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) |