Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
...
  • 6 commits
  • 3 files changed
  • 0 commit comments
  • 1 contributor
Showing with 409 additions and 65 deletions.
  1. +1 −1  LanguageVisualizer/parser.js
  2. +106 −64 on_character.js
  3. +302 −0 p.js
View
2  LanguageVisualizer/parser.js
1 addition, 1 deletion not shown
View
170 on_character.js
@@ -17,8 +17,8 @@ var factories = [];
factories[NAME] = function(id, parent, state)
{
- return function(character)
- {
+ return s = function(character)
+ {//console.log(s.tabs + "into " + rules[id][1] + " " + rules[id] + " -> " + rules[id][2]);
return parser(rules[id][2], parent)(character);
}
}
@@ -26,7 +26,7 @@ factories[NAME] = function(id, parent, state)
factories[DOT] = function(id, parent, state)
{
return function(character)
- {
+ {//console.log(i + " [" + character + "] accept any");
if (character === null)
return failure;
@@ -43,7 +43,7 @@ factories[CHARACTER_CLASS] = function(id, parent, state)
return function(character)
{
- console.log("[" + character + "]" + " from class: " + rule[1] + " resulting: " + (character !== null && character.match(rule[1])) + " " + (parent === failure));
+ //console.log(i + " [" + character + "]" + " from class: " + rule[1] + " resulting: " + (character !== null && character.match(rule[1])) + " " + (parent === failure));
if (character !== null && character.match(rule[1]))
return parent;
@@ -56,7 +56,7 @@ factories[STRING_LITERAL] = function(id, parent, state)
return function(character)
{
var string = rules[id][1];
-console.log("[" + character + "]" + " from string: " + string + "[" + state + "] = " + string.charAt(state));
+//console.log(i + " [" + character + "]" + " from string: " + string + "[" + state + "] = " + string.charAt(state));
if (string.charAt(state) === character)
{
if (state === string.length - 1)
@@ -69,66 +69,101 @@ console.log("[" + character + "]" + " from string: " + string + "[" + state + "]
}
}
+Array.prototype.fancyPrint = function(index)
+{
+ var string = "";
+
+ for (var j=0;j<this.length;++j)
+ {
+ if (j === index)
+ string += "[" + this[j] + "] "
+ else
+ string += this[j] + " ";
+ }
+
+ return string;
+}
+
factories[SEQUENCE] = function(id, parent, state)
{
return function(character)
{
- rule = rules[id];
+ var rule = rules[id],
+ index = state + 1;
- // If not the last one...
- if (state + 1 < rule.length - 1)
- parent = parser(id, parent, state + 1);
+ if (index < rule.length - 1)
+ parent = parser(id, parent, index);
- return parser(rule[state + 1], parent)(character);
+ //console.log("=> " + id + " { " + rule.fancyPrint(index) + "} p = " + parent.id);
+
+ return parser(rule[index], parent)(character);
}
}
+function hasParent(parser, parent)
+{
+ var parserParent = parser.parent
+ return parserParent && (parserParent === parent || hasParent(parserParent, parent));
+}
+
function list(parent, first, rest)
{
if (!rest)
return first;
- items = function(character)
+ var items = function(character)
{
- first = first(character);
-
- if (first === parent)
- return parent;
-
- rest = rest(character);
-
- if (first === failure)
- return rest;
+ var r = rest;
+ //console.log("-> " + items.id + " " + first.state + " and rest is " + rest.id);
+ var firstResult = first(character);
+ //console.log("just called " + items.id + " " + firstResult.id + " " + rest.id);
+ if (firstResult !== failure && !hasParent(firstResult, parent))
+ return firstResult;
+
+// if (firstResult.parent !== parent)
+ //if (firstResult === parent){console.log("parent good");
+// return firstResult;
+
+ if (firstResult === success)
+ {
+ console.log("CRAZY for " + items.id);
+ return firstResult;
+ }
+ //console.log("???" + rest.id + " " + (rest === r));
- if (rest === failure)
- return first;
+ var restResult = rest(character);
+// console.log("-> " + items.id + " " + first.state + " => " + firstResult.id + " vs. " + restResult.id);
+ if (firstResult === failure){//console.log("yes");
+ return restResult;}
- return items;
- }
+ if (restResult === failure)
+ return firstResult;
+ return list(parent, firstResult, restResult);
+ };
+ items.id = "(" + first.id + ") (" + rest.id + ")";
+ items.parent = parent;
+// console.log("MAKING CHOICE " + items.id + " p = " + parent.id);
return items;
}
factories[ORDERED_CHOICE] = function(id, parent, state)
{
- return function(character)
- {
- var rule = rules[id],
- count = rule.length,
- parsers = null;
+ var rule = rules[id],
+ count = rule.length,
+ parsers = null;
- while (count-- > 1)
- parsers = list(parent, parser(rule[count], parent), parsers);
+ while (count-- > 1)
+ parsers = list(parent, parser(rule[count], parent), parsers);
- return parsers(character);
- }
+ return parsers;
}
factories[ZERO_OR_MORE] = function(id, parent, state)
{
var result = function(character)
{
- return list(parent, parser(rules[id][1], result), parent)(character);
+ return list(result, parser(rules[id][1], result), parent)(character);
}
return result;
@@ -141,7 +176,7 @@ factories[ONE_OR_MORE] = function(id, parent, state)
if (state === 0)
return parser(rules[id][1], parser(id, parent, state + 1))(character);
- return list(parent, parser(rules[id][1], result), parent)(character);
+ return list(result, parser(rules[id][1], result), parent)(character);
}
return result;
@@ -149,10 +184,7 @@ factories[ONE_OR_MORE] = function(id, parent, state)
factories[OPTIONAL] = function(id, parent, state)
{
- return function(character)
- {
- return list(parent, parser(rules[id][1], parent), parent)(character);
- }
+ return list(parent, parser(rules[id][1], parent), parent);
}
factories[NEGATIVE_LOOKAHEAD] = function(id, parent, state)
@@ -203,6 +235,8 @@ function success()
return success;
}
+success.id = "s";
+
function failure()
{
//console.log("failure");
@@ -211,36 +245,44 @@ function failure()
function parser(id, parent, state)
{
- return factories[rules[id][0]](id, parent, state || 0);
-}
-
-var rules = [
- [SEQUENCE, 1, 2, 3],
- [STRING_LITERAL, "abc"],
- [NEGATIVE_LOOKAHEAD, 4],
- [STRING_LITERAL, "def"],
- [STRING_LITERAL, "f"]
- /*
- [NAME, "start", 1],
- [SEQUENCE, 9, 5, 6, 7],
- [STRING_LITERAL, "abc"],
- [STRING_LITERAL, "abcd"],
- [ORDERED_CHOICE, 2, 3],
- [DOT],
- [CHARACTER_CLASS, "[abc]"],
- [ZERO_OR_MORE, 6],
- [STRING_LITERAL, "d"],
- [OPTIONAL, 8]*/
- ],
- input = "abcdef",//require("fs").readFileSync(process.argv[2]).toString(),
- lang = parser(0, success);
+ var x = factories[rules[id][0]](id, parent, state || 0);
+ x.rule = rules[id];
+ x.tabs = (parent.tabs || "") + " ";
+ x.rid = id + (parent.rid ? "." + parent.rid : "")
+ x.id = x.rid + "@" + (state || 0);
+ x.state = state || 0;
+ x.parent = parent;
+ return x;
+}
+if (true)
+{
+var json = JSON.parse(require("fs").readFileSync("/Users/tolmasky/Development/language/ParserSpeed/language2.js/grammar.json").toString()),
+ rules = json["table"],
+ input = require("fs").readFileSync("/Users/tolmasky/Development/language/on_character.js"/*process.argv[2]*/).toString(),
+ lang = parser(json["nameToUID"]["start"], success);//187
+}
+else
+{
+var json = JSON.parse(require("fs").readFileSync("/Users/tolmasky/Development/language/ParserSpeed/language2.js/simpler.json").toString()),
+ rules = json["table"],
+ input = "a",
+ lang = parser(json["nameToUID"]["AssignmentExpression"], success);
+}
+okidoke = false;
for (i = 0; i < input.length; ++i)
+{
+ console.log("\n[" + i +"] " + lang.id + "\n");
lang = lang(input.charAt(i));
-
+}
+okidoke = true;
+console.log("IS SUCCESS " + (lang === success))
+//return;
while (lang !== success && lang !== failure)
+{
+ console.log("\n[" + i +"] " + lang.id + "\n");
lang = lang(null);
-
+}
if (lang === success)
console.log("success");
else
View
302 p.js
@@ -0,0 +1,302 @@
+
+var NAME = 0,
+ DOT = 1,
+ CHARACTER_CLASS = 2,
+ ORDERED_CHOICE = 3,
+ SEQUENCE = 4,
+ STRING_LITERAL = 5,
+ ZERO_OR_MORE = 6,
+ ONE_OR_MORE = 7,
+ OPTIONAL = 8,
+ NEGATIVE_LOOKAHEAD = 9,
+ POSITIVE_LOOKAHEAD = 10,
+ ERROR_NAME = 11,
+ ERROR_CHOICE = 12;
+
+var factories = [];
+
+factories[NAME] = function(id, next, state)
+{
+ // No actual work is done here, just pass it down the line.
+ return parser(rules[id][2], next);
+}
+
+factories[DOT] = function(id, next, state)
+{
+ // Always succeed except if passed the end of the input.
+ return function(character)
+ {
+ return character === null ? failure : next;
+ }
+}
+
+factories[CHARACTER_CLASS] = function(id, next, state)
+{
+ var rule = rules[id];
+
+ if (typeof rule[1].valueOf() === "string")
+ rule[1] = new RegExp(rule[1]);
+
+ return function(character)
+ {
+ if (character === null || !rule[1].test(character))
+ return failure;
+
+ return next;
+ }
+}
+
+factories[STRING_LITERAL] = function(id, next, state)
+{
+ return function(character)
+ {
+ var string = rules[id][1],
+ length = string.length;
+
+ if (character === null)
+ return length === 0 ? next : failure;
+
+ if (string.charAt(state) === character)
+ return state === length - 1 ? next : parser(id, next, state + 1);
+
+ return failure;
+ }
+}
+
+factories[SEQUENCE] = function(id, next, state)
+{
+ var rule = rules[id],
+ index = state + 1;
+
+ if (index < rule.length - 1)
+ return parser(rule[index], parser(id, next, index));
+
+ return parser(rule[index], next);
+}
+
+function capture(parser)
+{
+ var captured = function(character, uncapture)
+ {
+ if (uncapture)
+ return parser;
+
+ parser = parser(character);
+captured.hash = parser.hash;
+ return parser === failure ? parser : captured;
+ }
+captured.hash = parser.hash;
+ return captured;
+}
+
+function markedChoice(first, rest, next, mark, markCalled)
+{
+ var f = function(character)
+ {
+console.log("GOING IN!");
+ var firstResult = first(character);
+console.log("GOT BACK " + firstResult.hash);
+ // if first's next got called...
+ if (firstResult === mark)
+ return next;
+
+ if (firstResult === markCalled)
+ return next(character);
+ if (!firstResult.hash)
+ console.log(firstResult + "");
+if (firstResult.hash && firstResult.hash.substr(0, 4) === "MARK")
+ console.log("WTF " + character);
+ var restResult = rest(character);
+
+ if (firstResult === failure)
+ return restResult;
+
+// if (restResult === failure)
+// return firstResult;
+
+ return markedChoice(firstResult, restResult, next, mark, markCalled);
+ }
+ f.firster = first;
+ f.mark = mark;
+ f.hash = "(" + first.hash + " OR " + rest.hash + ")";
+ return f;
+}
+
+var counter = 0;
+
+function choice(id, next, rest)
+{console.log("IM MARKING " + next.hash);
+ function mark(character)
+ {
+ console.log("called with " + character + " " + next);
+ return markCalled;
+ }
+
+ function markCalled(character)
+ {
+ console.log("should never happen");
+ return markCalled;
+ }
+mark.hash = "MARKED(" + counter + ")[" + next.hash + "]";
+markCalled.hash = "MARKED_CALLED(" + (counter++) + ")[" + next.hash + "]";
+ return markedChoice(parser(id, mark), rest, next, mark, markCalled);
+}
+
+factories[ORDERED_CHOICE] = function(id, next, state)
+{console.log("brand new!");
+ var rule = rules[id],
+ index = state + 1;
+
+ if (index < rule.length - 1)
+ return choice(rule[index], next, parser(id, next, index));
+
+ return parser(rule[index], next);
+
+ var rule = rules[id],
+ count = rule.length,
+ parsers = parser(rule[--count], next);
+
+ while (count-- > 1)
+ parsers = choice(rule[count], next, parsers);
+
+ return parsers;
+}
+
+factories[ZERO_OR_MORE] = function(id, next, state)
+{
+ return choice(rules[id][1], parser(id, next, state + 1), next);
+}
+
+factories[ONE_OR_MORE] = function(id, next, state)
+{
+ if (state === 0)
+ return parser(rules[id][1], parser(id, next, state + 1));
+
+ return choice(rules[id][1], parser(id, next, state + 1), next);
+}
+
+factories[OPTIONAL] = function(id, next, state)
+{
+ return choice(rules[id][1], next, next);
+}
+
+function dependency(lookahead, parser, expected, unexpected)
+{
+ return function(character)
+ {
+ var lookaheadResult = lookahead(character),
+ parserResult = parser(character);
+
+ if (lookahead === expected)
+ return parserResult;
+
+ if (lookahead === unexpected)
+ return failure;
+
+ return dependency(lookaheadResult, parserResult, expected, unexpected);
+ }
+}
+
+factories[NEGATIVE_LOOKAHEAD] = function(id, next, state)
+{
+ return dependency(parser(rules[id][1], success), next, failure, success);
+}
+
+factories[POSITIVE_LOOKAHEAD] = function(id, next, state)
+{
+ return dependency(parser(rules[id][1], success), next, success, failure);
+}
+
+function success()
+{
+ //console.log("success");
+ return success;
+}
+
+success.id = "s";
+success.nameo = "success";
+success.hash = "success";
+
+function failure()
+{
+ //console.log("failure");
+ return failure;
+}
+
+failure.id = "failure";
+failure.nameo = "faliure";
+failure.hash = "failure";
+
+var parserCache = { };
+okidoke = false;
+function description(id)
+{
+ switch (rules[id][0])
+ {
+ case NAME: return "(" + rules[id][1] + ") ";
+ case DOT: return "[DOT] ";
+ case CHARACTER_CLASS: return rules[id][1] + " ";
+ case ORDERED_CHOICE: return "[CHOICE] ";
+ case SEQUENCE: return "[SEQ] ";
+ case STRING_LITERAL: return "\"" + rules[id][1] + "\" ";
+/*
+ ZERO_OR_MORE = 6,
+ ONE_OR_MORE = 7,
+ OPTIONAL = 8,
+ NEGATIVE_LOOKAHEAD = 9,
+ POSITIVE_LOOKAHEAD = 10,
+ ERROR_NAME = 11,
+ ERROR_CHOICE = 12;*/
+ }
+
+ return "";
+}
+
+function parser(id, next, state)
+{parserCache = { };
+ var hash = id + "@" + (state || 0) + " -> " + next.hash;
+
+ if (parserCache.hasOwnProperty(hash))
+ return parserCache[hash];
+
+ parserCache[hash] = function(character)
+ {
+ console.log("entering " + description(id) + hash);
+ return factories[rules[id][0]](id, next, state || 0)(character);
+ }
+
+ parserCache[hash].hash = hash;
+
+ return parserCache[hash];
+}
+
+function read(path)
+{
+ return require("fs").readFileSync(path).toString();
+}
+
+var json = JSON.parse(read(process.argv[2])),
+ rules = json["table"],
+ input = process.argv[3],//read(process.argv[3]),
+ lang = parser(json["nameToUID"]["start"], success);//DecimalLiteral
+console.log(input);
+for (i = 0; i < input.length; ++i)
+{
+ console.log("[" + i + "] = " + input.charAt(i) + " : " + lang.hash);
+ lang = lang(input.charAt(i));
+ console.log("[" + i + "] = " + input.charAt(i) + " : " + lang.hash);
+ parserCache = { };
+}
+okidoke = true;
+console.log("DONE AT INPUT END " + (lang === success) + " " + lang + " " + (lang.firster ? lang.firster.hash + " " + (lang.mark === lang.firster) : ""));
+
+while (lang !== success && lang !== failure)
+{
+ lang = lang(null);
+ parserCache = { };
+}
+
+if (lang === success)
+ console.log("success");
+else
+ console.log("failure");

No commit comments for this range

Something went wrong with that request. Please try again.