diff --git a/Makefile b/Makefile index f2b8eed..3429464 100644 --- a/Makefile +++ b/Makefile @@ -13,13 +13,10 @@ all: js_files css_files bower_copy .PHONY: js_files css_files bower_copy # Rules to minify our .js files -js_files: js/jsonl.min.js js/cssparser.js +js_files: js/jsonl.min.js js/cssparser.min.js js/%.min.js: js/%.js $(call mkdir,$(dir $@)) uglifyjs "$^" > "$@" -js/%.js: %.grammar.js - $(call mkdir,$(dir $@)) - node "$^" > "$@" js/%.js: %.y $(call mkdir,$(dir $@)) jison "$^" -o "$@" diff --git a/jsonl.grammar.js b/jsonl.grammar.js deleted file mode 100644 index ec37e19..0000000 --- a/jsonl.grammar.js +++ /dev/null @@ -1,90 +0,0 @@ -// -// compile with: -// node jsonl_grammar.js > js/jsonl.js -// uglify js/jsonl.js > js/jsonl.min.js -// -var Generator = require("jison").Generator; - -exports.grammar = { - "comment": "ECMA-262 5th Edition, 15.12.1 The JSON Grammar. Parses JSON strings into objects. This parser supports a 'lenient' version of JSON that doesn't require quotes around identifiers.", - "author": "Zach Carter; Ian Prest", - - "lex": { - "macros": { - "digit": "[0-9]", - "esc": "\\\\", - "int": "-?(?:[0-9]|[1-9][0-9]+)", - "exp": "(?:[eE][-+]?[0-9]+)", - "frac": "(?:\\.[0-9]+)" - }, - "rules": [ - ["\\s+", "/* skip whitespace */"], - ["{int}{frac}?{exp}?\\b", "return 'NUMBER';"], - ["\"(?:{esc}[\"bfnrt/{esc}]|{esc}u[a-fA-F0-9]{4}|[^\"{esc}]|\\(|\\))*\"", "yytext = eval(yytext); return 'STRING';"], - ["\\{", "return '{'"], - ["\\}", "return '}'"], - ["\\[", "return '['"], - ["\\]", "return ']'"], - [",", "return ','"], - [":", "return ':'"], - ["true\\b", "return 'TRUE'"], - ["false\\b", "return 'FALSE'"], - ["null\\b", "return 'NULL'"], - ["[_a-zA-Z][_a-zA-Z0-9]*", "return 'IDENTIFIER'" ] - ] - }, - - "tokens": "STRING NUMBER { } [ ] , : TRUE FALSE NULL IDENTIFIER", - "start": "JSONText", - - "bnf": { - "JSONString": [[ "STRING", "$$ = yytext;" ]], - "JSONIdentifier": [[ "STRING", "$$ = yytext;" ], - [ "IDENTIFIER", "$$ = yytext;" ]], - - "JSONNumber": [[ "NUMBER", "$$ = Number(yytext);" ]], - - "JSONNullLiteral": [[ "NULL", "$$ = null;" ]], - - "JSONBooleanLiteral": [[ "TRUE", "$$ = true;" ], - [ "FALSE", "$$ = false;" ]], - - - "JSONText": [[ "JSONValue", "return $$ = $1;" ]], - - "JSONValue": [[ "JSONNullLiteral", "$$ = $1;" ], - [ "JSONBooleanLiteral", "$$ = $1;" ], - [ "JSONString", "$$ = $1;" ], - [ "JSONNumber", "$$ = $1;" ], - [ "JSONObject", "$$ = $1;" ], - [ "JSONArray", "$$ = $1;" ]], - - "JSONObject": [[ "{ }", "$$ = {};" ], - [ "{ JSONMemberList }", "$$ = $2;" ]], - - "JSONMember": [[ "JSONIdentifier : JSONValue", "$$ = [$1, $3];" ]], - - "JSONMemberList": [[ "JSONMember", "$$ = {}; $$[$1[0]] = $1[1];" ], - [ "JSONMemberList , JSONMember", "$$ = $1; $1[$3[0]] = $3[1];" ]], - - "JSONArray": [[ "[ ]", "$$ = [];" ], - [ "[ JSONElementList ]", "$$ = $2;" ]], - - "JSONArrayValue": [[ "JSONValue", "$$ = $1;" ], - [ "", "$$ = undefined;" ]], - - "JSONElementList": [[ "JSONValue", "$$ = [$1];" ], - [ "JSONElementList , JSONArrayValue", "$$ = $1; $1.push($3);" ]] - } -}; - -var options = {type: "slr", moduleType: "commonjs", moduleName: "jsonl"}; - -exports.main = function main (args) { - var code = new Generator(exports.grammar, options).generate(); - console.log(code); -}; - -if (require.main === module) - exports.main(); - diff --git a/jsonl.y b/jsonl.y new file mode 100644 index 0000000..0b97f7c --- /dev/null +++ b/jsonl.y @@ -0,0 +1,98 @@ +/* ECMA-262 5th Edition, 15.12.1 The JSON Grammar. */ +/* Parses JSON strings into objects. */ +/* This parser supports a 'lenient' version of JSON that doesn't require quotes around identifiers. */ +/* Author: Zach Carter; Ian Prest (lenient bits) */ + +%lex +/* Lexer Macros */ +digit [0-9] +int \-?(?:[0-9]|[1-9][0-9]+) +exp (?:[eE][-+]?[0-9]+) +frac (?:\.[0-9]+) +esc \\ + +%% +/* Lexical Tokens */ +\s+ /* skip whitespace */ +{int}{frac}?{exp}?\b return 'NUMBER'; +'"'(?:{esc}["bfnrt/{esc}]|{esc}u[a-fA-F0-9]{4}|[^"{esc}]|\(|\))*'"' yytext = eval(yytext); return 'STRING'; +'{' return '{' +'}' return '}' +'[' return '[' +']' return ']' +',' return ',' +':' return ':' +'true'\b return 'TRUE' +'false'\b return 'FALSE' +'null'\b return 'NULL' +[_a-zA-Z][_a-zA-Z0-9]* return 'IDENTIFIER' + +/lex + +/* language grammar */ +%start JSONText +%% + +JSONString + : STRING { $$ = yytext; } + ; + +JSONIdentifier + : STRING { $$ = yytext; } + | IDENTIFIER { $$ = yytext; } + ; + +JSONNumber + : NUMBER { $$ = Number(yytext); } + ; + +JSONNullLiteral + : NULL { $$ = null; } + ; + +JSONBooleanLiteral + : TRUE { $$ = true; } + | FALSE { $$ = false; } + ; + +JSONText + : JSONValue { return $$ = $1; } + ; + +JSONValue + : JSONNullLiteral { $$ = $1; } + | JSONBooleanLiteral { $$ = $1; } + | JSONString { $$ = $1; } + | JSONNumber { $$ = $1; } + | JSONObject { $$ = $1; } + | JSONArray { $$ = $1; } + ; + +JSONObject + : '{' '}' { $$ = {}; } + | '{' JSONMemberList '}' { $$ = $2; } + ; + +JSONMember + : JSONIdentifier ':' JSONValue { $$ = [$1, $3]; } + ; + +JSONMemberList + : JSONMember { $$ = {}; $$[$1[0]] = $1[1]; } + | JSONMemberList ',' JSONMember { $$ = $1; $1[$3[0]] = $3[1]; } + ; + +JSONArray + : '[' ']' { $$ = []; } + | '[' JSONElementList ']' { $$ = $2; } + ; + +JSONArrayValue + : JSONValue { $$ = $1; } + | /*empty*/ { $$ = undefined; } + ; + +JSONElementList + : JSONValue { $$ = [$1]; } + | JSONElementList ',' JSONArrayValue { $$ = $1; $1.push($3); } + ; diff --git a/kb.html b/kb.html index c7ae18f..d621fbe 100644 --- a/kb.html +++ b/kb.html @@ -29,9 +29,9 @@ All rights reserved. - + - +