Created
August 12, 2013 11:39
-
-
Save niklaskorz/6210150 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import print_function | |
from ply import lex, yacc | |
tokens = ( | |
"LBRACE", "RBRACE", "LBRACKET", "RBRACKET", "COLON", | |
"STRING", "INT", "FLOAT", "COMMA", "NULL", "TRUE", "FALSE", | |
"WHITESPACE" | |
) | |
t_LBRACE = r"\{" | |
t_RBRACE = r"\}" | |
t_LBRACKET = r"\[" | |
t_RBRACKET = r"\]" | |
t_COLON = r":" | |
t_INT = r"[0-9]+(\.[0-9]+)?" | |
t_FLOAT = r"([0-9]+\.[0-9]*)|([0-9]*\.[0-9]+)" | |
t_COMMA = r"," | |
t_NULL = r"null" | |
t_TRUE = r"true" | |
t_FALSE = r"false" | |
def t_ignore_WHITESPACE(t): | |
r"[ \t\r\n]+" | |
t.lexer.lineno += t.value.count("\n") | |
def t_STRING(t): | |
r'\"([^\\"]|\\(.|\n))*\"' | |
t.lexer.lineno += t.value.count("\n") | |
return t | |
def t_error(t): | |
print("Lexer error:", t.value) | |
lexer = lex.lex() | |
precedence = ( | |
) | |
def p_object(p): | |
"object : LBRACE kvpairs RBRACE" | |
p[0] = p[2] | |
def p_kvpairs(p): | |
"""kvpairs : kvpair | |
| kvpairs COMMA kvpair""" | |
if len(p) == 4: | |
p[1].update(p[3]) | |
p[0] = p[1] | |
def p_kvpair(p): | |
"kvpair : string COLON value" | |
p[0] = {p[1]: p[3]} | |
def p_value(p): | |
"""value : string | |
| number | |
| object | |
| array | |
| bool | |
| null""" | |
p[0] = p[1] | |
def p_string(p): | |
"string : STRING" | |
p[0] = p[1][1:-1] | |
def p_number(p): | |
"""number : int | |
| float""" | |
p[0] = p[1] | |
def p_int(p): | |
"int : INT" | |
p[0] = int(p[1]) | |
def p_float(p): | |
"float : FLOAT" | |
p[0] = float(p[1]) | |
def p_array(p): | |
"array : LBRACKET values RBRACKET" | |
p[0] = p[2] | |
def p_values(p): | |
"""values : value | |
| values COMMA value""" | |
if len(p) == 4: | |
p[0] = p[1] + [p[3]] | |
else: | |
p[0] = [p[1]] | |
def p_bool(p): | |
"""bool : TRUE | |
| FALSE""" | |
p[0] = p[1] == "true" | |
def p_null(p): | |
"null : NULL" | |
p[0] = None | |
def p_error(p): | |
print("Syntax error '{0.value}' in line {0.lineno}".format(p)) | |
parser = yacc.yacc() | |
def parse(s): | |
return parser.parse(s, lexer=lexer) | |
if __name__ == "__main__": | |
import sys | |
assert(len(sys.argv) > 1) | |
with open(sys.argv[1]) as f: | |
data = parse(f.read()) | |
print(data) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment