diff --git a/lib/cli.js b/lib/cli.js index 4bd502528..f5ffc7ff0 100755 --- a/lib/cli.js +++ b/lib/cli.js @@ -167,14 +167,14 @@ cli.processGrammars = function processGrammars(file, lexFile, jsonMode) { grammar = ebnfParser.parse(file); } } catch (e) { - throw new Error('Could not parse jison grammar'); + throw new Error('Could not parse jison grammar\nError: ' + e); } try { if (lexFile) { grammar.lex = require('lex-parser').parse(lexFile); } } catch (e) { - throw new Error('Could not parse lex grammar'); + throw new Error('Could not parse lex grammar\nError: ' + e); } return grammar; }; diff --git a/ports/csharp/Jison/Jison.v12.suo b/ports/csharp/Jison/Jison.v12.suo new file mode 100644 index 000000000..c17dc66d2 Binary files /dev/null and b/ports/csharp/Jison/Jison.v12.suo differ diff --git a/ports/csharp/Jison/Jison/Jison.csproj b/ports/csharp/Jison/Jison/Jison.csproj index 59df70a60..173fd5861 100644 --- a/ports/csharp/Jison/Jison/Jison.csproj +++ b/ports/csharp/Jison/Jison/Jison.csproj @@ -71,18 +71,19 @@ True Resources.resx - + + + + - - - + @@ -122,7 +123,5 @@ - - - + \ No newline at end of file diff --git a/ports/csharp/Jison/Jison/Template.cs b/ports/csharp/Jison/Jison/Template.cs index 40e224b7e..71c1fc8ff 100644 --- a/ports/csharp/Jison/Jison/Template.cs +++ b/ports/csharp/Jison/Jison/Template.cs @@ -6,745 +6,834 @@ /**/namespace Jison/**/ { - public /**/class Parser/**/ - { - public ParserSymbols Symbols; - public Dictionary Terminals; - public Dictionary Productions; - public Dictionary Table; - public Dictionary DefaultActions; - public string Version = "0.4.2"; - public bool Debug = false; - - public const int None = 0; - public const int Shift = 1; - public const int Reduce = 2; - public const int Accept = 3; - - public void Trace() - { - - } - - /**/public Parser/**/() - { - //Setup Parser - //@@PARSER_INJECT@@ - - //Setup Lexer - //@@LEXER_INJECT@@ - } - - public /**/ParserValue/**/ ParserPerformAction(ref /**/ParserValue/**/ thisS, ref /**/ParserValue/**/ yy, ref int yystate, ref JList ss) - { - var so = ss.Count - 1;//@@ParserPerformActionInjection@@ - return null; - } - - public ParserSymbol ParserLex() - { - var token = LexerLex();//end = 1 + public /**/class Parser/**//**extends**/ + { + public ParserSymbols Symbols; + public Dictionary Terminals; + public Dictionary Productions; + public Dictionary Table; + public Dictionary DefaultActions; + public string Version = "0.4.2"; + public bool Debug = false; + + public const int None = 0; + public const int Shift = 1; + public const int Reduce = 2; + public const int Accept = 3; + public JList UnputStack = new JList(); + + public void Trace() + { + + } + + /**/public Parser/**/() + { + //Setup Parser + //@@PARSER_INJECT@@ + + //Setup Lexer + //@@LEXER_INJECT@@ + } + + public /**/ParserValue/**/ ParserPerformAction(ref /**/ParserValue/**/ thisS, ref /**/ParserValue/**/ yy, ref int yystate, ref JList ss) + { + var so = ss.Count - 1;//@@ParserPerformActionInjection@@ + return null; + } + + public ParserSymbol ParserLex() + { + var token = LexerLex();//end = 1 if (token != null) { return token; } - return Symbols["end"]; - } - - public void ParseError(string error, ParserError hash = null) - { - throw new InvalidOperationException(error); - } - - public void LexerError(string error, LexerError hash = null) - { - throw new InvalidOperationException(error); - } - - public /**/ParserValue/**/ Parse(string input) - { - if (Table == null) { - throw new Exception("Empty table"); - } - var stack = new JList - { - new ParserCachedAction(new ParserAction(0, Table[0])) - }; - var vstack = new JList - { - new /**/ParserValue/**/() - }; - var yy = new /**/ParserValue/**/(); - var _yy = new /**/ParserValue/**/(); - var v = new /**/ParserValue/**/(); - int recovering = 0; - ParserSymbol symbol = null; - ParserAction action = null; - string errStr = ""; - ParserSymbol preErrorSymbol = null; - ParserState state = null; - - SetInput(input); - - while (true) - { - // retreive state number from top of stack - state = stack.Last().Action.State; - - // use default actions if available - if (state != null && DefaultActions.ContainsKey(state.Index)) - { - action = DefaultActions[state.Index]; - } - else - { - if (symbol == null) - { - symbol = ParserLex(); - } - // read action for current state and first input - if (state != null && state.Actions.ContainsKey(symbol.Index)) - { - action = state.Actions[symbol.Index]; - } - else - { - action = null; - } - } - - if (action == null) - { - if (recovering > 0) - { - // Report error - var expected = new Stack{}; - foreach(var p in Table[state.Index].Actions) - { - expected.Push(Terminals[p.Value.Action].Name); - } - - errStr = "Parse error on line " + (Yy.LineNo + 1).ToString() + ":" + '\n' + - ShowPosition() + '\n' + - "Expecting " + String.Join(", ", expected) + - ", got '" + - (symbol != null ? Terminals[symbol.Index].ToString() : "NOTHING") + "'"; - - ParseError(errStr, new ParserError(Match, state, symbol, Yy.LineNo, yy.Loc, expected)); - } - } - - /*if (state.IsArray()) { - this.parseError("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol); - }*/ - - if (state == null || action == null) - { - break; - } - - switch (action.Action) - { - case Shift: - stack.Push(new ParserCachedAction(action, symbol)); - vstack.Push(Yy.Clone()); - - symbol = null; - if (preErrorSymbol == null) - { // normal execution/no error - yy = Yy.Clone(); - if (recovering > 0) recovering--; - } else { // error just occurred, resume old lookahead f/ before error - symbol = preErrorSymbol; - preErrorSymbol = null; - } - break; - - case Reduce: - int len = Productions[action.State.Index].Len; - // perform semantic action - _yy = vstack[vstack.Count - len]; - - if (Ranges != null) - { - Yy.Loc.Range = new ParserRange( - vstack[vstack.Count - len].Loc.Range.X, - vstack.Last().Loc.Range.Y - ); - } - - var value = ParserPerformAction(ref _yy, ref yy, ref action.State.Index, ref vstack); - - if (value != null) - { - return value; - } - - // pop off stack - while (len > 0) - { - stack.Pop(); - vstack.Pop(); - len--; - } - - if (_yy == null) - { - vstack.Push(new /**/ParserValue/**/()); - } - else - { - vstack.Push(_yy.Clone()); - } - var nextSymbol = Productions[action.State.Index].Symbol; - // goto new state = table[STATE][NONTERMINAL] - var nextState = stack.Last().Action.State; - var nextAction = nextState.Actions[nextSymbol.Index]; - - stack.Push(new ParserCachedAction(nextAction, nextSymbol)); - - break; - case Accept: - return v; - } - } - - return v; - } - - /* Jison generated lexer */ - public ParserSymbol Eof = new ParserSymbol("Eof", 1); - public /**/ParserValue/**/ Yy = new /**/ParserValue/**/(); - public string Match = ""; - public string Matched = ""; - public Stack ConditionStack; - public Dictionary Rules; - public Dictionary Conditions; - public bool Done = false; - public bool Less; - public bool _More; - public string _Input; - public int Offset; - public DictionaryRanges; - public bool Flex = false; - - public void SetInput(string input) - { - _Input = input; - _More = Less = Done = false; - Yy.LineNo = Yy.Leng = 0; - Matched = Match = ""; - ConditionStack = new Stack(); - ConditionStack.Push("INITIAL"); - - if (Ranges != null) - { - Yy.Loc = new ParserLocation(new ParserRange(0,0)); - } else { - Yy.Loc = new ParserLocation(); - } - - Offset = 0; - } - - public string Input() - { - string ch = _Input[0].ToString(); - Yy.Text += ch; - Yy.Leng++; - Offset++; - Match += ch; - Matched += ch; - Match lines = Regex.Match(ch, "/(?:\r\n?|\n).*/"); - if (lines.Success) { - Yy.LineNo++; - Yy.Loc.LastLine++; - } else { - Yy.Loc.LastColumn++; - } - - if (Ranges != null) - { - Yy.Loc.Range.Y++; - } - - _Input = _Input.Substring(1); - return ch; - } - - public void Unput(string ch) - { - int len = ch.Length; - var lines = Regex.Split(ch, "/(?:\r\n?|\n)/"); - - _Input = ch + _Input; - Yy.Text = Yy.Text.Substring(0, len - 1); - Offset -= len; - var oldLines = Regex.Split(Match, "/(?:\r\n?|\n)/"); - Match = Match.Substring(0, Match.Length - 1); - Matched = Matched.Substring(0, Matched.Length - 1); - - if ((lines.Length - 1) > 0) Yy.LineNo -= lines.Length - 1; - var r = Yy.Loc.Range; - - Yy.Loc = new ParserLocation( - Yy.Loc.FirstLine, - Yy.LineNo + 1, - Yy.Loc.FirstColumn, - ( - lines.Length > 0 ? - ( - lines.Length == oldLines.Length ? - Yy.Loc.FirstColumn : - 0 - ) + oldLines[oldLines.Length - lines.Length].Length - lines[0].Length : - Yy.Loc.FirstColumn - len - ) - ); - - if (Ranges.Count > 0) { - Yy.Loc.Range = new ParserRange(r.X, r.X + Yy.Leng - len); - } - } - - public void More() - { - _More = true; - } - - public string PastInput() - { - var past = Matched.Substring(0, Matched.Length - Match.Length); - return (past.Length > 20 ? "..." + Regex.Replace(past.Substring(-20), "/\n/", "") : ""); - } - - public string UpcomingInput() - { - var next = Match; - if (next.Length < 20) - { - next += _Input.Substring(0, (next.Length > 20 ? 20 - next.Length : next.Length)); - } - return Regex.Replace(next.Substring(0, (next.Length > 20 ? 20 - next.Length : next.Length)) + (next.Length > 20 ? "..." : ""), "/\n/", ""); - } - - public string ShowPosition() - { - var pre = PastInput(); - - var c = ""; - for (var i = 0; i < pre.Length; i++) - { - c += "-"; - } - - return pre + UpcomingInput() + '\n' + c + "^"; - } - - public ParserSymbol Next() - { - if (Done == true) - { - return Eof; - } - - if (String.IsNullOrEmpty(_Input)) - { - Done = true; - } - - if (_More == false) - { - Yy.Text = ""; - Match = ""; - } - - var rules = CurrentRules(); - string match = ""; - bool matched = false; - int index = 0; - Regex rule; - for (int i = 0; i < rules.Count; i++) - { - rule = Rules[rules[i]]; - var tempMatch = rule.Match(_Input); - if (tempMatch.Success == true && (match != null || tempMatch.Length > match.Length)) { - match = tempMatch.Value; - matched = true; - index = i; - if (!Flex) { - break; - } - } - } - if ( matched ) - { - Match lineCount = Regex.Match(match, "/\n.*/"); - - Yy.LineNo += lineCount.Length; - Yy.Loc.FirstLine = Yy.Loc.LastLine; - Yy.Loc.LastLine = Yy.LineNo + 1; - Yy.Loc.FirstColumn = Yy.Loc.LastColumn; - Yy.Loc.LastColumn = lineCount.Length > 0 ? lineCount.Length - 1 : Yy.Loc.LastColumn + match.Length; - - Yy.Text += match; - Match += match; - Matched += match; - - Yy.Leng = Yy.Text.Length; - if (Ranges != null) - { - Yy.Loc.Range = new ParserRange(Offset, Offset += Yy.Leng); - } - _More = false; - _Input = _Input.Substring(match.Length); + return Symbols["end"]; + } + + public void ParseError(string error, ParserError hash = null) + { + throw new InvalidOperationException(error); + } + + public void LexerError(string error, LexerError hash = null) + { + throw new InvalidOperationException(error); + } + + public /**/ParserValue/**/ Parse(string input) + { + if (Table == null) { + throw new Exception("Empty table"); + } + var stack = new JList + { + new ParserCachedAction(new ParserAction(0, Table[0])) + }; + var vstack = new JList + { + new /**/ParserValue/**/() + }; + var yy = new /**/ParserValue/**/(); + var _yy = new /**/ParserValue/**/(); + var v = new /**/ParserValue/**/(); + int recovering = 0; + ParserSymbol symbol = null; + ParserAction action = null; + string errStr = ""; + ParserSymbol preErrorSymbol = null; + ParserState state = null; + + SetInput(input); + + while (true) + { + // retreive state number from top of stack + state = stack.Last().Action.State; + + // use default actions if available + if (state != null && DefaultActions.ContainsKey(state.Index)) + { + action = DefaultActions[state.Index]; + } + else + { + if (symbol == null) + { + symbol = ParserLex(); + } + // read action for current state and first input + if (state != null && state.Actions.ContainsKey(symbol.Index)) + { + action = state.Actions[symbol.Index]; + } + else + { + action = null; + } + } + + if (action == null) + { + if (recovering > 0) + { + // Report error + var expected = new Stack{}; + foreach(var p in Table[state.Index].Actions) + { + expected.Push(Terminals[p.Value.Action].Name); + } + + errStr = "Parse error on line " + (Yy.LineNo + 1).ToString() + ":" + '\n' + + ShowPosition() + '\n' + + "Expecting " + String.Join(", ", expected) + + ", got '" + + (symbol != null ? Terminals[symbol.Index].ToString() : "NOTHING") + "'"; + + ParseError(errStr, new ParserError(Match, state, symbol, Yy.LineNo, yy.Loc, expected)); + } + } + + /*if (state.IsArray()) { + this.parseError("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol); + }*/ + + if (state == null || action == null) + { + break; + } + + switch (action.Action) + { + case Shift: + stack.Push(new ParserCachedAction(action, symbol)); + vstack.Push(Yy.Clone()); + + symbol = null; + if (preErrorSymbol == null) + { // normal execution/no error + yy = Yy.Clone(); + if (recovering > 0) recovering--; + } else { // error just occurred, resume old lookahead f/ before error + symbol = preErrorSymbol; + preErrorSymbol = null; + } + break; + + case Reduce: + int len = Productions[action.State.Index].Len; + // perform semantic action + _yy = vstack[vstack.Count - len]; + + if (Ranges != null) + { + Yy.Loc.Range = new ParserRange( + vstack[vstack.Count - len].Loc.Range.X, + vstack.Last().Loc.Range.Y + ); + } + + var value = ParserPerformAction(ref _yy, ref yy, ref action.State.Index, ref vstack); + + if (value != null) + { + return value; + } + + // pop off stack + while (len > 0) + { + stack.Pop(); + vstack.Pop(); + len--; + } + + if (_yy == null) + { + vstack.Push(new /**/ParserValue/**/()); + } + else + { + vstack.Push(_yy.Clone()); + } + var nextSymbol = Productions[action.State.Index].Symbol; + // goto new state = table[STATE][NONTERMINAL] + var nextState = stack.Last().Action.State; + var nextAction = nextState.Actions[nextSymbol.Index]; + + stack.Push(new ParserCachedAction(nextAction, nextSymbol)); + + break; + case Accept: + return v; + } + } + + return v; + } + + /* Jison generated lexer */ + public ParserSymbol Eof = new ParserSymbol("Eof", 1); + public /**/ParserValue/**/ Yy = new /**/ParserValue/**/(); + public string Match = ""; + public Stack ConditionStack; + public Dictionary Rules; + public Dictionary Conditions; + public bool Done = false; + public bool Less; + public bool _More; + public InputReader _Input; + public int Offset; + public DictionaryRanges; + public bool Flex = false; + + public void SetInput(string input) + { + _Input = new InputReader(input); + _More = Less = Done = false; + Yy.LineNo = Yy.Leng = 0; + ConditionStack = new Stack(); + ConditionStack.Push("INITIAL"); + + if (Ranges != null) + { + Yy.Loc = new ParserLocation(new ParserRange(0,0)); + } else { + Yy.Loc = new ParserLocation(); + } + + Offset = 0; + } + + public string Input() + { + string ch = _Input.Ch(); + Yy.Text += ch; + Yy.Leng++; + Offset++; + Match += ch; + Match lines = Regex.Match(ch, "/(?:\r\n?|\n).*/"); + if (lines.Success) { + Yy.LineNo++; + Yy.Loc.LastLine++; + } else { + Yy.Loc.LastColumn++; + } + + if (Ranges != null) + { + Yy.Loc.Range.Y++; + } + + return ch; + } + + public void Unput(string ch) + { + var yy = new /**/ParserValue/**/(); + int len = ch.Length; + var lines = Regex.Split(ch, "/(?:\r\n?|\n)/"); + + _Input.unCh(ch.Length); + yy.Text = Yy.Text.Substring(0, len - 1); + Offset -= len; + var oldLines = Regex.Split(Match, "/(?:\r\n?|\n)/"); + Match = Match.Substring(0, Match.Length - 1); + + if ((lines.Length - 1) > 0) + { + yy.LineNo -= Yy.LineNo - lines.Length - 1; + } + var r = Yy.Loc.Range; + + yy.Loc = new ParserLocation( + Yy.Loc.FirstLine, + Yy.LineNo + 1, + Yy.Loc.FirstColumn, + ( + lines.Length > 0 ? + ( + lines.Length == oldLines.Length ? + Yy.Loc.FirstColumn : + 0 + ) + oldLines[oldLines.Length - lines.Length].Length - lines[0].Length : + Yy.Loc.FirstColumn - len + ) + ); + + if (Ranges.Count > 0) { + yy.Loc.Range = new ParserRange(r.X, r.X + Yy.Leng - len); + } + + UnputStack.Push(yy); + } + + public void More() + { + _More = true; + } + + public string PastInput() + { + var past = _Input.ToString().Substring(0, _Input.Position - Match.Length); + return (past.Length > 20 ? "..." + Regex.Replace(past.Substring(20), "/\n/", "") : ""); + } + + public string UpcomingInput() + { + var next = Match; + if (next.Length < 20) + { + next += _Input.ToString().Substring(0, (next.Length > 20 ? 20 - next.Length : next.Length)); + } + return Regex.Replace(next.Substring(0, (next.Length > 20 ? 20 - next.Length : next.Length)) + (next.Length > 20 ? "..." : ""), "/\n/", ""); + } + + public string ShowPosition() + { + var pre = PastInput(); + + var c = ""; + for (var i = 0; i < pre.Length; i++) + { + c += "-"; + } + + return pre + UpcomingInput() + '\n' + c + "^"; + } + + public ParserSymbol Next() + { + if (UnputStack.Count > 0) + { + Yy = UnputStack.Pop(); + } + + if (Done == true) + { + return Eof; + } + + if (_Input.Done) + { + Done = true; + } + + if (_More == false) + { + Yy.Text = ""; + Match = ""; + } + + var rules = CurrentRules(); + string match = ""; + bool matched = false; + int index = 0; + Regex rule; + for (int i = 0; i < rules.Count; i++) + { + rule = Rules[rules[i]]; + var tempMatch = _Input.Match(rule); + if (tempMatch.Success && tempMatch.Length > match.Length) { + match = tempMatch.Value; + matched = true; + index = i; + if (!Flex) { + break; + } + } + } + if ( matched ) + { + Match lineCount = Regex.Match(match, "/\n.*/"); + + Yy.LineNo += lineCount.Length; + Yy.Loc.FirstLine = Yy.Loc.LastLine; + Yy.Loc.LastLine = Yy.LineNo + 1; + Yy.Loc.FirstColumn = Yy.Loc.LastColumn; + Yy.Loc.LastColumn = lineCount.Length > 0 ? lineCount.Length - 1 : Yy.Loc.LastColumn + match.Length; + + Yy.Text += match; + Match += match; + + Yy.Leng = Yy.Text.Length; + if (Ranges != null) + { + Yy.Loc.Range = new ParserRange(Offset, Offset += Yy.Leng); + } + _More = false; + _Input.AddMatch(match); var ruleIndex = rules[index]; var nextCondition = ConditionStack.Peek(); dynamic action = LexerPerformAction(ruleIndex, nextCondition); - ParserSymbol token = Symbols[action]; - - if (Done == true && String.IsNullOrEmpty(_Input) == false) - { - Done = false; - } - - if (token.Index > -1) { - return token; - } else { - return null; - } - } - - if (String.IsNullOrEmpty(_Input)) { - return Symbols["EOF"]; - } else - { - LexerError("Lexical error on line " + (Yy.LineNo + 1) + ". Unrecognized text.\n" + ShowPosition(), new LexerError("", -1, Yy.LineNo)); - return null; - } - } - - public ParserSymbol LexerLex() - { - var r = Next(); - - while (r == null) - { - r = Next(); - } - - return r; - } - - public void Begin(string condition) - { - ConditionStack.Push(condition); - } - - public string PopState() - { - return ConditionStack.Pop(); - } - - public List CurrentRules() - { - var peek = ConditionStack.Peek(); - return Conditions[peek].Rules; - } - - public dynamic LexerPerformAction(int avoidingNameCollisions, string Yy_Start) - { - //@@LexerPerformActionInjection@@ - return -1; - } - } - - public class ParserLocation - { - public int FirstLine = 1; - public int LastLine = 0; - public int FirstColumn = 1; - public int LastColumn = 0; - public ParserRange Range; - - public ParserLocation() - { - } - - public ParserLocation(ParserRange range) - { - Range = range; - } - - public ParserLocation(int firstLine, int lastLine, int firstColumn, int lastColumn) - { - FirstLine = firstLine; - LastLine = lastLine; - FirstColumn = firstColumn; - LastColumn = lastColumn; - } - - public ParserLocation(int firstLine, int lastLine, int firstColumn, int lastColumn, ParserRange range) - { - FirstLine = firstLine; - LastLine = lastLine; - FirstColumn = firstColumn; - LastColumn = lastColumn; - Range = range; - } - } - - public class LexerConditions - { - public List Rules; - public bool Inclusive; - - public LexerConditions(List rules, bool inclusive) - { - Rules = rules; - Inclusive = inclusive; - } - } - - public class ParserProduction - { - public int Len = 0; - public ParserSymbol Symbol; - - public ParserProduction(ParserSymbol symbol) - { - Symbol = symbol; - } - - public ParserProduction(ParserSymbol symbol, int len) - { - Symbol = symbol; - Len = len; - } - } - - public class ParserCachedAction - { - public ParserAction Action; - public ParserSymbol Symbol; - - public ParserCachedAction(ParserAction action) - { - Action = action; - } - - public ParserCachedAction(ParserAction action, ParserSymbol symbol) - { - Action = action; - Symbol = symbol; - } - } - - public class ParserAction - { - public int Action; - public ParserState State; - public ParserSymbol Symbol; - - public ParserAction(int action) - { - Action = action; - } - - public ParserAction(int action, ref ParserState state) - { - Action = action; - State = state; - } - - public ParserAction(int action, ParserState state) - { - Action = action; - State = state; - } - - public ParserAction(int action, ref ParserSymbol symbol) - { - Action = action; - Symbol = symbol; - } - } - - public class ParserSymbol - { - public string Name; - public int Index = -1; - public IDictionary Symbols = new Dictionary(); - public IDictionary SymbolsByName = new Dictionary(); - - public ParserSymbol() - { - } - - public ParserSymbol(string name, int index) - { - Name = name; - Index = index; - } - - public void AddAction(ParserSymbol p) - { - Symbols.Add(p.Index, p); - SymbolsByName.Add(p.Name, p); - } - } - - public class ParserError - { - public String Text; - public ParserState State; - public ParserSymbol Symbol; - public int LineNo; - public ParserLocation Loc; - public Stack Expected; - - public ParserError(String text, ParserState state, ParserSymbol symbol, int lineNo, ParserLocation loc, Stack expected) - { - Text = text; - State = state; - Symbol = symbol; - LineNo = lineNo; - Loc = loc; - Expected = expected; - } - } - - public class LexerError - { - public String Text; - public int Token; - public int LineNo; - - public LexerError(String text, int token, int lineNo) - { - Text = text; - Token = token; - LineNo = lineNo; - } - } - - public class ParserState - { - public int Index; - public Dictionary Actions = new Dictionary(); - - public ParserState(int index) - { - Index = index; - } - - public void SetActions(ref Dictionary actions) - { - Actions = actions; - } - } - - public class ParserRange - { - public int X; - public int Y; - - public ParserRange(int x, int y) - { - X = x; - Y = y; - } - } - - public class ParserSymbols - { - private Dictionary SymbolsString = new Dictionary(); - private Dictionary SymbolsInt = new Dictionary(); - - public void Add(ParserSymbol symbol) - { - SymbolsInt.Add(symbol.Index, symbol); - SymbolsString.Add(symbol.Name, symbol); - } - - public ParserSymbol this[char name] - { - get - { - return SymbolsString[name.ToString()]; - } - } - - public ParserSymbol this[string name] - { - get - { - return SymbolsString[name]; - } - } - - public ParserSymbol this[int index] - { - get - { - if (index < 0) - { - return new ParserSymbol(); - } - return SymbolsInt[index]; - } - } - } - - public class ParserValue - { - public string Text; - public ParserLocation Loc; - public int Leng = 0; - public int LineNo = 0; - - public ParserValue() - { - } - - public ParserValue(ParserValue parserValue) - { - Text = parserValue.Text; - Leng = parserValue.Leng; - Loc = parserValue.Loc; - LineNo = parserValue.LineNo; - } - - public ParserValue Clone() - { - return new ParserValue(this); - } - } - - public class JList : List where T : class - { - public void Push(T item) - { - Add(item); - } - - public void Pop() - { - RemoveAt(Count - 1); - } - - new public T this[int index] - { - get - { - if (index >= Count || index < 0 || Count == 0) - { - return null; - } - return base[index]; - } - } - } + ParserSymbol token = Symbols[action]; + + if (Done == true || _Input.Done) + { + Done = false; + } + + if (token.Index > -1) { + return token; + } else { + return null; + } + } + + if (_Input.Done) { + return Symbols["EOF"]; + } else + { + LexerError("Lexical error on line " + (Yy.LineNo + 1) + ". Unrecognized text.\n" + ShowPosition(), new LexerError("", -1, Yy.LineNo)); + return null; + } + } + + public ParserSymbol LexerLex() + { + var r = Next(); + + while (r == null) + { + r = Next(); + } + + return r; + } + + public void Begin(string condition) + { + ConditionStack.Push(condition); + } + + public string PopState() + { + return ConditionStack.Pop(); + } + + public List CurrentRules() + { + var peek = ConditionStack.Peek(); + return Conditions[peek].Rules; + } + + public dynamic LexerPerformAction(int avoidingNameCollisions, string Yy_Start) + { + //@@LexerPerformActionInjection@@ + return -1; + } + } + + public class ParserLocation + { + public int FirstLine = 1; + public int LastLine = 0; + public int FirstColumn = 1; + public int LastColumn = 0; + public ParserRange Range; + + public ParserLocation() + { + } + + public ParserLocation(ParserRange range) + { + Range = range; + } + + public ParserLocation(int firstLine, int lastLine, int firstColumn, int lastColumn) + { + FirstLine = firstLine; + LastLine = lastLine; + FirstColumn = firstColumn; + LastColumn = lastColumn; + } + + public ParserLocation(int firstLine, int lastLine, int firstColumn, int lastColumn, ParserRange range) + { + FirstLine = firstLine; + LastLine = lastLine; + FirstColumn = firstColumn; + LastColumn = lastColumn; + Range = range; + } + + public ParserLocation Clone() + { + var parserLocation = new ParserLocation(FirstLine, LastLine,FirstColumn,LastColumn); + + if (Range != null) + { + parserLocation.Range = Range.Clone(); + } + + return parserLocation; + } + } + + public class LexerConditions + { + public List Rules; + public bool Inclusive; + + public LexerConditions(List rules, bool inclusive) + { + Rules = rules; + Inclusive = inclusive; + } + } + + public class ParserProduction + { + public int Len = 0; + public ParserSymbol Symbol; + + public ParserProduction(ParserSymbol symbol) + { + Symbol = symbol; + } + + public ParserProduction(ParserSymbol symbol, int len) + { + Symbol = symbol; + Len = len; + } + } + + public class ParserCachedAction + { + public ParserAction Action; + public ParserSymbol Symbol; + + public ParserCachedAction(ParserAction action) + { + Action = action; + } + + public ParserCachedAction(ParserAction action, ParserSymbol symbol) + { + Action = action; + Symbol = symbol; + } + } + + public class ParserAction + { + public int Action; + public ParserState State; + public ParserSymbol Symbol; + + public ParserAction(int action) + { + Action = action; + } + + public ParserAction(int action, ref ParserState state) + { + Action = action; + State = state; + } + + public ParserAction(int action, ParserState state) + { + Action = action; + State = state; + } + + public ParserAction(int action, ref ParserSymbol symbol) + { + Action = action; + Symbol = symbol; + } + } + + public class ParserSymbol + { + public string Name; + public int Index = -1; + public IDictionary Symbols = new Dictionary(); + public IDictionary SymbolsByName = new Dictionary(); + + public ParserSymbol() + { + } + + public ParserSymbol(string name, int index) + { + Name = name; + Index = index; + } + + public void AddAction(ParserSymbol p) + { + Symbols.Add(p.Index, p); + SymbolsByName.Add(p.Name, p); + } + } + + public class ParserError + { + public String Text; + public ParserState State; + public ParserSymbol Symbol; + public int LineNo; + public ParserLocation Loc; + public Stack Expected; + + public ParserError(String text, ParserState state, ParserSymbol symbol, int lineNo, ParserLocation loc, Stack expected) + { + Text = text; + State = state; + Symbol = symbol; + LineNo = lineNo; + Loc = loc; + Expected = expected; + } + } + + public class LexerError + { + public String Text; + public int Token; + public int LineNo; + + public LexerError(String text, int token, int lineNo) + { + Text = text; + Token = token; + LineNo = lineNo; + } + } + + public class ParserState + { + public int Index; + public Dictionary Actions = new Dictionary(); + + public ParserState(int index) + { + Index = index; + } + + public void SetActions(ref Dictionary actions) + { + Actions = actions; + } + } + + public class ParserRange + { + public int X; + public int Y; + + public ParserRange(int x, int y) + { + X = x; + Y = y; + } + + public ParserRange Clone() + { + var parserRange = new ParserRange(X, Y); + return parserRange; + } + } + + public class ParserSymbols + { + private Dictionary SymbolsString = new Dictionary(); + private Dictionary SymbolsInt = new Dictionary(); + + public void Add(ParserSymbol symbol) + { + SymbolsInt.Add(symbol.Index, symbol); + SymbolsString.Add(symbol.Name, symbol); + } + + public ParserSymbol this[char name] + { + get + { + return SymbolsString[name.ToString()]; + } + } + + public ParserSymbol this[string name] + { + get + { + return SymbolsString[name]; + } + } + + public ParserSymbol this[int index] + { + get + { + if (index < 0) + { + return new ParserSymbol(); + } + return SymbolsInt[index]; + } + } + } + + public class ParserValue + { + public string Text; + public ParserLocation Loc; + public int Leng = 0; + public int LineNo = 0; + + public ParserValue() + { + } + + public ParserValue(string text, ParserLocation loc, int leng, int lineNo) + { + Text = text; + Loc = loc; + Leng = leng; + LineNo = lineNo; + } + + public ParserValue Clone() + { + var parserValue = new ParserValue(); + parserValue.Text = this.Text; + + + return parserValue; + } + } + + public class JList : List where T : class + { + public void Push(T item) + { + Add(item); + } + + public T Pop() + { + var i = Math.Max(0, Count); + if (i == 0) + { + return null; + } + + var val = this[i]; + RemoveAt(i); + return val; + } + + new public T this[int index] + { + get + { + if (index >= Count || index < 0 || Count == 0) + { + return null; + } + return base[index]; + } + } + } + + + public class InputReader + { + + public bool Done = false; + public string Input; + public int Length; + public JList Matches = new JList(); + public int Position = 0; + + public InputReader(string input) + { + Input = input; + Length = input.Length; + } + + public void AddMatch (string match) { + Matches.Push(match); + Position += match.Length; + Done = (Position >= Length); + } + + public string Ch() + { + var ch = Input[Position].ToString(); + AddMatch(ch); + return ch; + } + + public void unCh(int chLength) + { + Position -= chLength; + Position = Math.Max(0, Position); + Done = (Position >= Length); + } + + public string Substring(int start, int end) { + start = (start != 0 ? Position + start : Position); + end = (end != 0 ? start + end : Length); + return Input.Substring(start, end); + } + + public Match Match(Regex rule) { + var match = rule.Match(Input, Position); + return match; + } + + public new string ToString() + { + return String.Join("", Matches.ToArray()); + } + } } \ No newline at end of file diff --git a/ports/csharp/Jison/Jison/Test.cs b/ports/csharp/Jison/Jison/Test.cs index 1dd965950..d85161ede 100644 --- a/ports/csharp/Jison/Jison/Test.cs +++ b/ports/csharp/Jison/Jison/Test.cs @@ -1,7 +1,6 @@ using System; -using jQuerySheet; -namespace jQuerySheet +namespace Sheet { public class Test { @@ -11,30 +10,19 @@ public Test () public static void Main() { - Spreadsheet.Spreadsheets = new SpreadsheetsDictionary(); - var spreadsheetsDictionary = new SpreadsheetDictionary(); - Spreadsheet.Spreadsheets.Add(0, spreadsheetsDictionary); - var row = new RowDictionary(); - spreadsheetsDictionary.Add(0, row); + var spreadsheets = new Spreadsheets(); + var spreadsheet = spreadsheets.AddSpreadsheet(); - var cellA1 = new Cell(0, 0, 0); - cellA1.Value = "250"; - var cellB1 = new Cell(0, 0, 1); - cellB1.Value = "250"; - var cellC1 = new Cell(0, 0, 2); - cellC1.Formula = "800 - SUM(A1:B1) + 100"; - cellC1.HasFormula = true; + var row = spreadsheet.AddRow(); - row.Add(0, cellA1); - row.Add(1, cellB1); - row.Add(2, cellC1); + var cellA1 = row.AddCell("250"); + var cellB1 = row.AddCell("250"); + var cellC1 = row.AddCell("800 - (SUM(A1:B1) + 100)", true); - //var spreadsheet = new Spreadsheet(); - //spreadsheet.Calc(); - - var parsedCell = Spreadsheet.Spreadsheets[0][0][2]; - var value = parsedCell.UpdateValue(); - value = value; + var cell = spreadsheet["C", 1]; + var value = cell.UpdateValue(); + Console.Write(value.ToDouble()); + Console.Read(); } } } diff --git a/ports/csharp/Jison/Jison/Test/Cell.cs b/ports/csharp/Jison/Jison/Test/Cell.cs index c24a9d242..4343987af 100644 --- a/ports/csharp/Jison/Jison/Test/Cell.cs +++ b/ports/csharp/Jison/Jison/Test/Cell.cs @@ -1,14 +1,10 @@ using System; using System.Collections.Generic; -namespace jQuerySheet +namespace Sheet { public class Cell { - public Cell () - { - } - public int Row; public int Col; public int Spreadsheet; @@ -16,12 +12,15 @@ public Cell () public Boolean HasFormula; public string Formula; public Expression Exp; - public DateTime CalcLast = new DateTime(); public int CalcCount = 0; - public Stack State = new Stack(); - + public Row Parent; + + public Cell() + { + } + public Cell(int spreadsheet, int row, int col) { Spreadsheet = spreadsheet; @@ -41,23 +40,25 @@ public Expression UpdateValue() if (HasFormula && State.Count < 1) { State.Push ("Parsing"); CalcCount++; - var formula = new Formula (); + var formula = new Formula(); + formula.Setup(this); var value = formula.Parse (Formula); State.Pop (); return value; - } else { - var exp = new Expression(); - double num; - if (double.TryParse(Value, out num)) - { - exp.Set(num); - } - else - { - exp.Set(Value); - } - return exp; } + + var exp = new Expression(); + double num; + if (double.TryParse(Value, out num)) + { + exp.Set(num); + } + else + { + exp.Set(Value); + } + return exp; + } } } diff --git a/ports/csharp/Jison/Jison/Test/Expression.cs b/ports/csharp/Jison/Jison/Test/Expression.cs index 769d100f2..d5ed45fb9 100644 --- a/ports/csharp/Jison/Jison/Test/Expression.cs +++ b/ports/csharp/Jison/Jison/Test/Expression.cs @@ -1,29 +1,53 @@ using System; using System.Collections.Generic; +using Jison; -namespace jQuerySheet +namespace Sheet { public class Expression : ParserValue { public bool ValueSet = false; public string Type; + public bool BoolValue; + public double DoubleValue; + public List Children; + + public Expression() + { + } - public Expression(){} - public Expression(Expression value) - { - Text = value.Text; - Leng = value.Leng; - Loc = value.Loc; - LineNo = value.LineNo; - ValueSet = value.ValueSet; - BoolValue = value.BoolValue; - Children = value.Children; - DoubleValue = value.DoubleValue; - } - - public Expression Clone() + public new Expression Clone() { - return new Expression(this); + var expression = new Expression(); + expression.Text = Text; + if (Loc != null) + { + expression.Loc = Loc.Clone(); + } + expression.Leng = Leng; + expression.LineNo = LineNo; + + expression.ValueSet = ValueSet; + expression.Type = Type; + expression.ValueSet = ValueSet; + expression.BoolValue = BoolValue; + + if (Children != null) + { + expression.Children = new JList(); + + foreach (var child in Children) + { + if (this != child) + { + expression.Children.Add(child.Clone()); + } + } + } + + expression.DoubleValue = DoubleValue; + + return expression; } public Expression(string value) @@ -31,12 +55,12 @@ public Expression(string value) Text = value; } - public bool BoolValue; public bool ToBool() { ValueSet = true; BoolValue = Convert.ToBoolean (Text); Type = "bool"; + Text = BoolValue.ToString(); return BoolValue; } public void Set(bool value) { @@ -45,11 +69,14 @@ public void Set(bool value) { Type = "bool"; } - - public double DoubleValue; public double ToDouble() { - ValueSet = true; + if (Type == "double") + { + return DoubleValue; + } + + ValueSet = true; if (!String.IsNullOrEmpty (Text) || DoubleValue != 0) { double num; if (double.TryParse(Text, out num)) { @@ -87,35 +114,33 @@ public void Add(Expression value) value.ToDouble(); DoubleValue += value.DoubleValue; Type = "double"; + Text = DoubleValue.ToString(); } public void Set(double value) { DoubleValue = value; + Text = value.ToString(); ValueSet = true; Type = "double"; } - public string ToString() { ValueSet = true; - Type = "string"; return Text; } + public void Set(string value) { Text = value; ValueSet = true; Type = "string"; } + public void Concat(Expression value) { Text += value.Text; Type = "string"; } - - - - - public List Children; + public void Push(Expression value) { if (Children == null) { diff --git a/ports/csharp/Jison/Jison/Test/Formula.cs b/ports/csharp/Jison/Jison/Test/Formula.cs index bc1ec4011..f88b6bb60 100644 --- a/ports/csharp/Jison/Jison/Test/Formula.cs +++ b/ports/csharp/Jison/Jison/Test/Formula.cs @@ -4,9 +4,9 @@ using System.Linq; -namespace jQuerySheet +namespace Sheet { - public class Formula + public class Formula : FormulaBase { public ParserSymbols Symbols; public Dictionary Terminals; @@ -20,6 +20,7 @@ public class Formula public const int Shift = 1; public const int Reduce = 2; public const int Accept = 3; + public JList UnputStack = new JList(); public void Trace() { @@ -1729,42 +1730,42 @@ public Formula() Rules = new Dictionary { - {0, new Regex(@"^(?:\s+)")}, - {1, new Regex(@"^(?:""(\\[""]|[^""])*"")")}, - {2, new Regex(@"^(?:'(\\[']|[^'])*')")}, - {3, new Regex(@"^(?:[A-Za-z]{1,}[A-Za-z_0-9]+(?=[(]))")}, - {4, new Regex(@"^(?:([0]?[1-9]|1[0-2])[:][0-5][0-9]([:][0-5][0-9])?[ ]?(AM|am|aM|Am|PM|pm|pM|Pm))")}, - {5, new Regex(@"^(?:([0]?[0-9]|1[0-9]|2[0-3])[:][0-5][0-9]([:][0-5][0-9])?)")}, - {6, new Regex(@"^(?:SHEET[0-9]+)")}, - {7, new Regex(@"^(?:\$[A-Za-z]+\$[0-9]+)")}, - {8, new Regex(@"^(?:[A-Za-z]+[0-9]+)")}, - {9, new Regex(@"^(?:[A-Za-z]+(?=[(]))")}, - {10, new Regex(@"^(?:[A-Za-z]{1,}[A-Za-z_0-9]+)")}, - {11, new Regex(@"^(?:[A-Za-z_]+)")}, - {12, new Regex(@"^(?:[0-9]+)")}, - {13, new Regex(@"^(?:\\s)")}, - {14, new Regex(@"^(?:[.])")}, - {15, new Regex(@"^(?::)")}, - {16, new Regex(@"^(?:;)")}, - {17, new Regex(@"^(?:,)")}, - {18, new Regex(@"^(?:\*)")}, - {19, new Regex(@"^(?:\/)")}, - {20, new Regex(@"^(?:-)")}, - {21, new Regex(@"^(?:\+)")}, - {22, new Regex(@"^(?:\^)")}, - {23, new Regex(@"^(?:\()")}, - {24, new Regex(@"^(?:\))")}, - {25, new Regex(@"^(?:>)")}, - {26, new Regex(@"^(?:<)")}, - {27, new Regex(@"^(?:NOT\b)")}, - {28, new Regex(@"^(?:E\b)")}, - {29, new Regex(@"^(?:"")")}, - {30, new Regex(@"^(?:')")}, - {31, new Regex(@"^(?:!)")}, - {32, new Regex(@"^(?:=)")}, - {33, new Regex(@"^(?:%)")}, - {34, new Regex(@"^(?:[#])")}, - {35, new Regex(@"^(?:$)")} + {0, new Regex(@"\G(?:\s+)")}, + {1, new Regex(@"\G(?:""(\\[""]|[^""])*"")")}, + {2, new Regex(@"\G(?:'(\\[']|[^'])*')")}, + {3, new Regex(@"\G(?:[A-Za-z]{1,}[A-Za-z_0-9]+(?=[(]))")}, + {4, new Regex(@"\G(?:([0]?[1-9]|1[0-2])[:][0-5][0-9]([:][0-5][0-9])?[ ]?(AM|am|aM|Am|PM|pm|pM|Pm))")}, + {5, new Regex(@"\G(?:([0]?[0-9]|1[0-9]|2[0-3])[:][0-5][0-9]([:][0-5][0-9])?)")}, + {6, new Regex(@"\G(?:SHEET[0-9]+)")}, + {7, new Regex(@"\G(?:\$[A-Za-z]+\$[0-9]+)")}, + {8, new Regex(@"\G(?:[A-Za-z]+[0-9]+)")}, + {9, new Regex(@"\G(?:[A-Za-z]+(?=[(]))")}, + {10, new Regex(@"\G(?:[A-Za-z]{1,}[A-Za-z_0-9]+)")}, + {11, new Regex(@"\G(?:[A-Za-z_]+)")}, + {12, new Regex(@"\G(?:[0-9]+)")}, + {13, new Regex(@"\G(?:\\s)")}, + {14, new Regex(@"\G(?:[.])")}, + {15, new Regex(@"\G(?::)")}, + {16, new Regex(@"\G(?:;)")}, + {17, new Regex(@"\G(?:,)")}, + {18, new Regex(@"\G(?:\*)")}, + {19, new Regex(@"\G(?:\/)")}, + {20, new Regex(@"\G(?:-)")}, + {21, new Regex(@"\G(?:\+)")}, + {22, new Regex(@"\G(?:\^)")}, + {23, new Regex(@"\G(?:\()")}, + {24, new Regex(@"\G(?:\))")}, + {25, new Regex(@"\G(?:>)")}, + {26, new Regex(@"\G(?:<)")}, + {27, new Regex(@"\G(?:NOT\b)")}, + {28, new Regex(@"\G(?:E\b)")}, + {29, new Regex(@"\G(?:"")")}, + {30, new Regex(@"\G(?:')")}, + {31, new Regex(@"\G(?:!)")}, + {32, new Regex(@"\G(?:=)")}, + {33, new Regex(@"\G(?:%)")}, + {34, new Regex(@"\G(?:[#])")}, + {35, new Regex(@"\G(?:$)")} }; Conditions = new Dictionary @@ -1793,10 +1794,12 @@ public Expression ParserPerformAction(ref Expression thisS, ref Expression yy, r break; case 3: - + // + break; case 4: - + // + break; case 5: @@ -1842,7 +1845,8 @@ public Expression ParserPerformAction(ref Expression thisS, ref Expression yy, r break; case 9: - + // + thisS = ss[so - 1]; break; case 10: @@ -1863,7 +1867,8 @@ public Expression ParserPerformAction(ref Expression thisS, ref Expression yy, r break; case 12: - + // + ss[so-3].Set(ss[so-3].Text != ss[so].Text); thisS = ss[so-3]; @@ -1871,7 +1876,8 @@ public Expression ParserPerformAction(ref Expression thisS, ref Expression yy, r break; case 13: - + // + ss[so-2].Set(ss[so-2].Text != ss[so].Text); thisS = ss[so-2]; @@ -1970,47 +1976,47 @@ public Expression ParserPerformAction(ref Expression thisS, ref Expression yy, r - thisS = Spreadsheet.CellValue(Location.ParseFixed(ss[so].Text)); + thisS = MySpreadsheets.CellValue(MySpreadsheet.ParseFixed(ss[so].Text)); break; case 29: - - - - thisS = Spreadsheet.CellValue(Location.ParseFixed(ss[so-2].Text), Location.ParseFixed(ss[so].Text)); + + + + thisS = MySpreadsheets.CellValue(MySpreadsheet.ParseFixed(ss[so - 2].Text), MySpreadsheet.ParseFixed(ss[so].Text)); break; case 30: - - - - thisS = Spreadsheet.CellValue(Location.Parse(ss[so].Text)); + + + + thisS = MySpreadsheets.CellValue(MySpreadsheet.Parse(ss[so].Text)); break; case 31: - - - - thisS = Spreadsheet.CellValue(Location.Parse(ss[so-2].Text), Location.Parse(ss[so].Text)); + + + + thisS = MySpreadsheets.CellValue(MySpreadsheet.Parse(ss[so - 2].Text), MySpreadsheet.Parse(ss[so].Text)); break; case 32: - - - - thisS = Spreadsheet.CellValue(Location.ParseRemote(ss[so-2].Text, ss[so].Text)); + + + + thisS = MySpreadsheets.CellValue(MySpreadsheet.ParseRemote(ss[so - 2].Text, ss[so].Text)); break; case 33: - - - - thisS = Spreadsheet.CellValue(Location.ParseRemote(ss[so-4].Text, ss[so-2].Text), Location.ParseRemote(ss[so-4].Text, ss[so].Text)); + + + + thisS = MySpreadsheets.CellValue(MySpreadsheet.ParseRemote(ss[so - 4].Text, ss[so - 2].Text), MySpreadsheet.ParseRemote(ss[so - 4].Text, ss[so].Text)); break; @@ -2281,24 +2287,22 @@ public Expression Parse(string input) public ParserSymbol Eof = new ParserSymbol("Eof", 1); public Expression Yy = new Expression(); public string Match = ""; - public string Matched = ""; public Stack ConditionStack; public Dictionary Rules; public Dictionary Conditions; public bool Done = false; public bool Less; public bool _More; - public string _Input; + public InputReader _Input; public int Offset; public DictionaryRanges; public bool Flex = false; public void SetInput(string input) { - _Input = input; + _Input = new InputReader(input); _More = Less = Done = false; Yy.LineNo = Yy.Leng = 0; - Matched = Match = ""; ConditionStack = new Stack(); ConditionStack.Push("INITIAL"); @@ -2314,12 +2318,11 @@ public void SetInput(string input) public string Input() { - string ch = _Input[0].ToString(); + string ch = _Input.Ch(); Yy.Text += ch; Yy.Leng++; Offset++; Match += ch; - Matched += ch; Match lines = Regex.Match(ch, "/(?:\r\n?|\n).*/"); if (lines.Success) { Yy.LineNo++; @@ -2333,26 +2336,28 @@ public string Input() Yy.Loc.Range.Y++; } - _Input = _Input.Substring(1); return ch; } public void Unput(string ch) { + var yy = new Expression(); int len = ch.Length; var lines = Regex.Split(ch, "/(?:\r\n?|\n)/"); - _Input = ch + _Input; - Yy.Text = Yy.Text.Substring(0, len - 1); + _Input.unCh(ch.Length); + yy.Text = Yy.Text.Substring(0, len - 1); Offset -= len; var oldLines = Regex.Split(Match, "/(?:\r\n?|\n)/"); Match = Match.Substring(0, Match.Length - 1); - Matched = Matched.Substring(0, Matched.Length - 1); - if ((lines.Length - 1) > 0) Yy.LineNo -= lines.Length - 1; + if ((lines.Length - 1) > 0) + { + yy.LineNo -= Yy.LineNo - lines.Length - 1; + } var r = Yy.Loc.Range; - Yy.Loc = new ParserLocation( + yy.Loc = new ParserLocation( Yy.Loc.FirstLine, Yy.LineNo + 1, Yy.Loc.FirstColumn, @@ -2368,8 +2373,10 @@ public void Unput(string ch) ); if (Ranges.Count > 0) { - Yy.Loc.Range = new ParserRange(r.X, r.X + Yy.Leng - len); + yy.Loc.Range = new ParserRange(r.X, r.X + Yy.Leng - len); } + + UnputStack.Push(yy); } public void More() @@ -2379,8 +2386,8 @@ public void More() public string PastInput() { - var past = Matched.Substring(0, Matched.Length - Match.Length); - return (past.Length > 20 ? "..." + Regex.Replace(past.Substring(-20), "/\n/", "") : ""); + var past = _Input.ToString().Substring(0, _Input.Position - Match.Length); + return (past.Length > 20 ? "..." + Regex.Replace(past.Substring(20), "/\n/", "") : ""); } public string UpcomingInput() @@ -2388,7 +2395,7 @@ public string UpcomingInput() var next = Match; if (next.Length < 20) { - next += _Input.Substring(0, (next.Length > 20 ? 20 - next.Length : next.Length)); + next += _Input.ToString().Substring(0, (next.Length > 20 ? 20 - next.Length : next.Length)); } return Regex.Replace(next.Substring(0, (next.Length > 20 ? 20 - next.Length : next.Length)) + (next.Length > 20 ? "..." : ""), "/\n/", ""); } @@ -2408,12 +2415,17 @@ public string ShowPosition() public ParserSymbol Next() { - if (Done == true) + if (UnputStack.Count > 0) + { + Yy = UnputStack.Pop(); + } + + if (Done == true) { return Eof; } - if (String.IsNullOrEmpty(_Input)) + if (_Input.Done) { Done = true; } @@ -2432,8 +2444,8 @@ public ParserSymbol Next() for (int i = 0; i < rules.Count; i++) { rule = Rules[rules[i]]; - var tempMatch = rule.Match(_Input); - if (tempMatch.Success == true && (match != null || tempMatch.Length > match.Length)) { + var tempMatch = _Input.Match(rule); + if (tempMatch.Success && tempMatch.Length > match.Length) { match = tempMatch.Value; matched = true; index = i; @@ -2454,7 +2466,6 @@ public ParserSymbol Next() Yy.Text += match; Match += match; - Matched += match; Yy.Leng = Yy.Text.Length; if (Ranges != null) @@ -2462,13 +2473,13 @@ public ParserSymbol Next() Yy.Loc.Range = new ParserRange(Offset, Offset += Yy.Leng); } _More = false; - _Input = _Input.Substring(match.Length); + _Input.AddMatch(match); var ruleIndex = rules[index]; var nextCondition = ConditionStack.Peek(); dynamic action = LexerPerformAction(ruleIndex, nextCondition); ParserSymbol token = Symbols[action]; - if (Done == true && String.IsNullOrEmpty(_Input) == false) + if (Done == true || _Input.Done) { Done = false; } @@ -2480,7 +2491,7 @@ public ParserSymbol Next() } } - if (String.IsNullOrEmpty(_Input)) { + if (_Input.Done) { return Symbols["EOF"]; } else { @@ -2655,6 +2666,18 @@ public ParserLocation(int firstLine, int lastLine, int firstColumn, int lastColu LastColumn = lastColumn; Range = range; } + + public ParserLocation Clone() + { + var parserLocation = new ParserLocation(FirstLine, LastLine,FirstColumn,LastColumn); + + if (Range != null) + { + parserLocation.Range = Range.Clone(); + } + + return parserLocation; + } } public class LexerConditions @@ -2817,6 +2840,12 @@ public ParserRange(int x, int y) X = x; Y = y; } + + public ParserRange Clone() + { + var parserRange = new ParserRange(X, Y); + return parserRange; + } } public class ParserSymbols @@ -2869,18 +2898,22 @@ public class ParserValue public ParserValue() { } - - public ParserValue(ParserValue parserValue) - { - Text = parserValue.Text; - Leng = parserValue.Leng; - Loc = parserValue.Loc; - LineNo = parserValue.LineNo; - } + + public ParserValue(string text, ParserLocation loc, int leng, int lineNo) + { + Text = text; + Loc = loc; + Leng = leng; + LineNo = lineNo; + } public ParserValue Clone() { - return new ParserValue(this); + var parserValue = new ParserValue(); + parserValue.Text = this.Text; + + + return parserValue; } } @@ -2891,9 +2924,17 @@ public void Push(T item) Add(item); } - public void Pop() + public T Pop() { - RemoveAt(Count - 1); + var i = Math.Max(0, Count - 1); + if (i == 0) + { + return null; + } + + var val = this[i]; + RemoveAt(i); + return val; } new public T this[int index] @@ -2908,4 +2949,57 @@ public void Pop() } } } + + + public class InputReader + { + + public bool Done = false; + public string Input; + public int Length; + public JList Matches = new JList(); + public int Position = 0; + + public InputReader(string input) + { + Input = input; + Length = input.Length; + } + + public void AddMatch (string match) { + Matches.Push(match); + Position += match.Length; + Done = (Position >= Length); + } + + public string Ch() + { + var ch = Input[Position].ToString(); + AddMatch(ch); + return ch; + } + + public void unCh(int chLength) + { + Position -= chLength; + Position = Math.Max(0, Position); + Done = (Position >= Length); + } + + public string Substring(int start, int end) { + start = (start != 0 ? Position + start : Position); + end = (end != 0 ? start + end : Length); + return Input.Substring(start, end); + } + + public Match Match(Regex rule) { + var match = rule.Match(Input, Position); + return match; + } + + public new string ToString() + { + return String.Join("", Matches.ToArray()); + } + } } \ No newline at end of file diff --git a/ports/csharp/Jison/Jison/Test/FormulaBase.cs b/ports/csharp/Jison/Jison/Test/FormulaBase.cs new file mode 100644 index 000000000..324e88c62 --- /dev/null +++ b/ports/csharp/Jison/Jison/Test/FormulaBase.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Sheet +{ + public class FormulaBase + { + public Cell Parent; + public Spreadsheet MySpreadsheet; + public Spreadsheets MySpreadsheets; + + public void Setup(Cell cell) + { + Parent = cell; + MySpreadsheet = cell.Parent.Parent; + MySpreadsheets = MySpreadsheet.Parent; + } + } +} diff --git a/ports/csharp/Jison/Jison/Test/Functions.cs b/ports/csharp/Jison/Jison/Test/Functions.cs index 4edce4b0a..af43a4242 100644 --- a/ports/csharp/Jison/Jison/Test/Functions.cs +++ b/ports/csharp/Jison/Jison/Test/Functions.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using Jison; -namespace jQuerySheet +namespace Sheet { public static class Functions { @@ -39,7 +39,7 @@ public static Expression Sum(Expression value) return firstChild; } - value.ToDouble (); + value.ToDouble(); return value; } } diff --git a/ports/csharp/Jison/Jison/Test/Location.cs b/ports/csharp/Jison/Jison/Test/Location.cs index 6864d4aec..edb812ab8 100644 --- a/ports/csharp/Jison/Jison/Test/Location.cs +++ b/ports/csharp/Jison/Jison/Test/Location.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Text.RegularExpressions; -namespace jQuerySheet +namespace Sheet { public class Location { @@ -48,26 +48,6 @@ public Location () static readonly public Regex Cell = new Regex("^([A-Z]+)([0-9]+)"); - public static Location Parse(string id) - { - return new Location(id); - } - - public static Location ParseRemote(string sheet, string id) - { - return new Location(sheet, id); - } - - public static Location ParseFixed(string id) - { - return new Location(id, true); - } - - public static Location ParseRemoteFixed(string sheet, string id) - { - return new Location(sheet, id, true); - } - public void ParseCellId(string id) { var match = Cell.Match(id); @@ -76,7 +56,6 @@ public void ParseCellId(string id) Col = Alphabet[match.Groups[1].Value]; Row = Convert.ToInt32(match.Groups[2].Value) - 1; } - Sheet = Spreadsheet.ActiveSpreadsheet; } public void ParseSheetId(string sheet) @@ -85,9 +64,10 @@ public void ParseSheetId(string sheet) Sheet = Convert.ToInt32(sheet); } - public Location(string id) + public Location(Spreadsheet spreadsheet, string id) { ParseCellId(id); + Sheet = spreadsheet.Index; } public Location(string sheet, string id) diff --git a/ports/csharp/Jison/Jison/Test/Row.cs b/ports/csharp/Jison/Jison/Test/Row.cs new file mode 100644 index 000000000..fe130b720 --- /dev/null +++ b/ports/csharp/Jison/Jison/Test/Row.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; + +namespace Sheet +{ + public class Row: Dictionary + { + public Spreadsheet Parent; + public int CellIndex = -1; + + public Row () + { + } + + public Cell AddCell() + { + return AddCell("", false); + } + + public Cell AddCell(string value) + { + return AddCell(value, false); + } + + public Cell AddCell(string value, bool isFormula) + { + var cell = new Cell(); + CellIndex++; + cell.Parent = this; + + if (isFormula) + { + cell.Formula = value; + cell.HasFormula = true; + } + else + { + cell.Value = value; + } + + Add(CellIndex, cell); + return cell; + } + + public Cell this[string col] + { + get { return this[Location.Alphabet[col]]; } + } + } +} + diff --git a/ports/csharp/Jison/Jison/Test/RowDictionary.cs b/ports/csharp/Jison/Jison/Test/RowDictionary.cs deleted file mode 100644 index a29ecd704..000000000 --- a/ports/csharp/Jison/Jison/Test/RowDictionary.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace jQuerySheet -{ - public class RowDictionary : Dictionary - { - public RowDictionary () - { - } - } -} - diff --git a/ports/csharp/Jison/Jison/Test/Spreadsheet.cs b/ports/csharp/Jison/Jison/Test/Spreadsheet.cs index 44be3f8fe..a8fdc7f10 100644 --- a/ports/csharp/Jison/Jison/Test/Spreadsheet.cs +++ b/ports/csharp/Jison/Jison/Test/Spreadsheet.cs @@ -1,73 +1,67 @@ -using System; -using System.Text; -using System.Threading.Tasks; +using System; using System.Collections.Generic; -namespace jQuerySheet +namespace Sheet { - public class Spreadsheet - { - static public int ActiveSpreadsheet = 0; - static public SpreadsheetsDictionary Spreadsheets; - - - public SpreadsheetsDictionary Calc() + public class Spreadsheet : Dictionary + { + public Spreadsheets Parent; + public int Index; + public int RowIndex = -1; + public Row AddRow() { - foreach (var Spreadsheet in Spreadsheets.Values) { - foreach (var row in Spreadsheet.Values) { - foreach (var cell in row) { - cell.Value.UpdateValue(); - } - } - } - - return Spreadsheets; + var row = new Row(); + RowIndex++; + row.Parent = this; + Add(RowIndex, row); + return row; } - public static DateTime CalcLast; + public Cell this[string colString, int rowInt] + { + get { + var row = this[rowInt - 1]; + + var colInt = Location.Alphabet[colString]; + var cell = row[colInt]; + return cell; + } + } - public static Expression UpdateCellValue(Cell cell) + public Cell this[int colInt, int rowInt] { - if (cell.HasFormula && cell.State.Count < 1) + get { - cell.State.Push("Parsing"); - cell.CalcCount++; - cell.CalcLast = CalcLast; - var formula = new Formula(); - var value = formula.Parse(cell.Formula); - cell.State.Pop(); - return value; + var row = this[rowInt]; + var cell = row[colInt]; + return cell; } - return cell.Exp; } - public static Expression CellValue(int spreadsheet, int row, int col) - { - var cell = Spreadsheets[spreadsheet][row][col]; - var value = UpdateCellValue(cell); - return value; - } + public Spreadsheet(int index) + : base() { + Index = index; + } - public static Expression CellValue(Location loc) + public Location Parse(string id) { - var cell = Spreadsheets[loc.Sheet][loc.Row][loc.Col]; - var value = UpdateCellValue(cell); - return value; + return new Location(this, id); } - public static Expression CellValue(Location locStart, Location locEnd) + public Location ParseRemote(string sheet, string id) { - var range = new Expression(); + return new Location(sheet, id); + } - for (var row = locStart.Row; row <= locEnd.Row; row++) - { - for (var col = locStart.Col; col <= locEnd.Col; col++) - { - range.Push(Spreadsheets[locStart.Sheet][row][col].UpdateValue()); - } - } + public Location ParseFixed(string id) + { + return new Location(id, true); + } - return range; + public Location ParseRemoteFixed(string sheet, string id) + { + return new Location(sheet, id, true); } - } + } } + diff --git a/ports/csharp/Jison/Jison/Test/SpreadsheetDictionary.cs b/ports/csharp/Jison/Jison/Test/SpreadsheetDictionary.cs deleted file mode 100644 index a4441bf0c..000000000 --- a/ports/csharp/Jison/Jison/Test/SpreadsheetDictionary.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Collections.Generic; -using jQuerySheet; - -namespace jQuerySheet -{ - public class SpreadsheetDictionary : Dictionary - { - public int RowIndex = -1; - public RowDictionary ActiveRow; - public void AddRow() - { - ActiveRow = new RowDictionary(); - RowIndex++; - Add (RowIndex, ActiveRow); - } - } -} - diff --git a/ports/csharp/Jison/Jison/Test/Spreadsheets.cs b/ports/csharp/Jison/Jison/Test/Spreadsheets.cs new file mode 100644 index 000000000..7831afec8 --- /dev/null +++ b/ports/csharp/Jison/Jison/Test/Spreadsheets.cs @@ -0,0 +1,88 @@ +using System; +using System.Linq; +using System.Collections.Generic; + +namespace Sheet +{ + public class Spreadsheets : Dictionary + { + public int ActiveSpreadsheet = -1; + public int SpreadsheetIndex = -1; + + public void Calc() + { + foreach (var spreadsheet in Values) { + foreach (var row in spreadsheet.Values) { + foreach (var cell in row) { + cell.Value.UpdateValue(); + } + } + } + } + + public DateTime CalcLast; + + public Expression UpdateCellValue(Cell cell) + { + if (cell.HasFormula && cell.State.Count < 1) + { + cell.State.Push("Parsing"); + cell.CalcCount++; + cell.CalcLast = CalcLast; + var formula = new Formula(); + var value = formula.Parse(cell.Formula); + cell.State.Pop(); + return value; + } + return cell.Exp; + } + + public Expression CellValue(int spreadsheet, int row, int col) + { + Cell cell = Values.ElementAt(spreadsheet) + .Values.ElementAt(row) + .Values.ElementAt(col); + + var value = UpdateCellValue(cell); + return value; + } + + public Expression CellValue(Location loc) + { + Cell cell = Values.ElementAt(loc.Sheet) + .Values.ElementAt(loc.Row) + .Values.ElementAt(loc.Col); + + var value = UpdateCellValue(cell); + return value; + } + + public Expression CellValue(Location locStart, Location locEnd) + { + var range = new Expression(); + + for (var row = locStart.Row; row <= locEnd.Row; row++) + { + for (var col = locStart.Col; col <= locEnd.Col; col++) + { + range.Push( + Values.ElementAt(locStart.Sheet) + .Values.ElementAt(row) + .Values.ElementAt(col).UpdateValue() + ); + } + } + + return range; + } + + public Spreadsheet AddSpreadsheet() + { + SpreadsheetIndex++; + var spreadsheet = new Spreadsheet(SpreadsheetIndex); + spreadsheet.Parent = this; + Add(SpreadsheetIndex, spreadsheet); + return spreadsheet; + } + } +} diff --git a/ports/csharp/Jison/Jison/Test/SpreadsheetsDictionary.cs b/ports/csharp/Jison/Jison/Test/SpreadsheetsDictionary.cs deleted file mode 100644 index 0c0dfa11e..000000000 --- a/ports/csharp/Jison/Jison/Test/SpreadsheetsDictionary.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace jQuerySheet -{ - public class SpreadsheetsDictionary : Dictionary - { - } -} - diff --git a/ports/csharp/Jison/Jison/Test/formula.jison b/ports/csharp/Jison/Jison/Test/formula.jison index 9814f4636..c37e931a8 100644 --- a/ports/csharp/Jison/Jison/Test/formula.jison +++ b/ports/csharp/Jison/Jison/Test/formula.jison @@ -1,5 +1,6 @@ //option parserValue:Expression -//option namespace:jQuerySheet +//option namespace:Sheet +//option extends:FormulaBase /* description: Parses end evaluates mathematical expressions. */ /* lexical grammar */ @@ -204,7 +205,10 @@ expression : { //js $$ = yy.handler.number.apply(yy.obj, [$2]); - // + + /*cs + $$ = $2; + */ } | expression '<' '=' expression { @@ -417,7 +421,7 @@ cell : //php $$ = $this->fixedCellValue($1); /*cs - $$ = Spreadsheet.CellValue(Location.ParseFixed($1.Text)); + $$ = MySpreadsheets.CellValue(MySpreadsheet.ParseFixed($1.Text)); */ } | FIXEDCELL ':' FIXEDCELL @@ -428,7 +432,7 @@ cell : //php $$ = $this->fixedCellRangeValue($1, $3); /*cs - $$ = Spreadsheet.CellValue(Location.ParseFixed($1.Text), Location.ParseFixed($3.Text)); + $$ = MySpreadsheets.CellValue(MySpreadsheet.ParseFixed($1.Text), MySpreadsheet.ParseFixed($3.Text)); */ } | CELL @@ -439,7 +443,7 @@ cell : //php $$ = $this->cellValue($1); /*cs - $$ = Spreadsheet.CellValue(Location.Parse($1.Text)); + $$ = MySpreadsheets.CellValue(MySpreadsheet.Parse($1.Text)); */ } | CELL ':' CELL @@ -450,7 +454,7 @@ cell : //php $$ = $this->cellRangeValue($1, $3); /*cs - $$ = Spreadsheet.CellValue(Location.Parse($1.Text), Location.Parse($3.Text)); + $$ = MySpreadsheets.CellValue(MySpreadsheet.Parse($1.Text), MySpreadsheet.Parse($3.Text)); */ } | SHEET '!' CELL @@ -461,7 +465,7 @@ cell : //php $$ = $this->remoteCellValue($1, $3); /*cs - $$ = Spreadsheet.CellValue(Location.ParseRemote($1.Text, $3.Text)); + $$ = MySpreadsheets.CellValue(MySpreadsheet.ParseRemote($1.Text, $3.Text)); */ } | SHEET '!' CELL ':' CELL @@ -472,7 +476,7 @@ cell : //php $$ = $this->remoteCellRangeValue($1, $3, $5); /*cs - $$ = Spreadsheet.CellValue(Location.ParseRemote($1.Text, $3.Text), Location.ParseRemote($1.Text, $5.Text)); + $$ = MySpreadsheets.CellValue(MySpreadsheet.ParseRemote($1.Text, $3.Text), MySpreadsheet.ParseRemote($1.Text, $5.Text)); */ } ; diff --git a/ports/csharp/Jison/Jison/bin/Debug/Jison.exe b/ports/csharp/Jison/Jison/bin/Debug/Jison.exe deleted file mode 100755 index 2d64ad580..000000000 Binary files a/ports/csharp/Jison/Jison/bin/Debug/Jison.exe and /dev/null differ diff --git a/ports/csharp/Jison/Jison/bin/Debug/Jison.exe.config b/ports/csharp/Jison/Jison/bin/Debug/Jison.exe.config deleted file mode 100644 index 8e1564635..000000000 --- a/ports/csharp/Jison/Jison/bin/Debug/Jison.exe.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/ports/csharp/Jison/Jison/bin/Debug/Jison.pdb b/ports/csharp/Jison/Jison/bin/Debug/Jison.pdb deleted file mode 100644 index 3c2fef7fb..000000000 Binary files a/ports/csharp/Jison/Jison/bin/Debug/Jison.pdb and /dev/null differ diff --git a/ports/csharp/Jison/Jison/bin/Debug/Jison.vshost.exe b/ports/csharp/Jison/Jison/bin/Debug/Jison.vshost.exe deleted file mode 100644 index 8c8451740..000000000 Binary files a/ports/csharp/Jison/Jison/bin/Debug/Jison.vshost.exe and /dev/null differ diff --git a/ports/csharp/Jison/Jison/bin/Debug/Jison.vshost.exe.config b/ports/csharp/Jison/Jison/bin/Debug/Jison.vshost.exe.config deleted file mode 100644 index 8e1564635..000000000 --- a/ports/csharp/Jison/Jison/bin/Debug/Jison.vshost.exe.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/ports/csharp/Jison/Jison/build.bat b/ports/csharp/Jison/Jison/build.bat new file mode 100644 index 000000000..a25546ea3 --- /dev/null +++ b/ports/csharp/Jison/Jison/build.bat @@ -0,0 +1 @@ +node csharp.js Test\formula.jison \ No newline at end of file diff --git a/ports/csharp/Jison/Jison/csharp.js b/ports/csharp/Jison/Jison/csharp.js index 76c5d8adf..4da738d95 100644 --- a/ports/csharp/Jison/Jison/csharp.js +++ b/ports/csharp/Jison/Jison/csharp.js @@ -24,9 +24,10 @@ exec("jison " + process.argv[2], function (error) { String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g, '');}; - var fileName = process.argv[2].replace(/(.jison|.json)/, '') + var jisonFileName = process.argv[2], + fileName = jisonFileName.replace('.jison', ''), comments = require(path.resolve(__dirname, '../../../comments.js')), - requirePath = fileName + '.js'; + requirePath = path.resolve(jisonFileName).replace('.jison', '') + '.js'; console.log("Opening newly created jison js file: " + fileName + '.js'); @@ -85,27 +86,31 @@ exec("jison " + process.argv[2], function (error) { } str = comments.parse(str); - str = str.replace(/(\d)\n/g, function () { + str = str.replace(/(\d)(\n|\r\n)/g, function () { return arguments[1] + ';\n'; }); return str; } - var FileName = fileName.charAt(0).toUpperCase() + fileName.slice(1); - var ClassName = FileName.replace(/^.*[\\\/]/, '').charAt(0).toUpperCase() + FileName.replace(/^.*[\\\/]/, '').slice(1); + function capitaliseFirstLetter(string) { + return string.charAt(0).toUpperCase() + string.slice(1); + } + + var FileName = capitaliseFirstLetter(fileName); var option = { 'using': '', 'namespace': 'Jison', - 'class': ClassName, + 'class': capitaliseFirstLetter(FileName.split(/[/\\]/g).pop()), 'fileName': FileName + '.cs', + 'extends': '', 'parserValue': '' }; - - if (fileName.search(/jison/) !== -1) { + if (jisonFileName.match(/jison$/i)) { var parserDefinition = fs.readFileSync(fileName + '.jison', "utf8"); parserDefinition = parserDefinition.split(/\n/g); + for (var i = 0; i < parserDefinition.length; i++) { if (parserDefinition[i].match('//option')) { parserDefinition[i] = parserDefinition[i].replace('//option ', '').trim(); @@ -115,7 +120,11 @@ exec("jison " + process.argv[2], function (error) { } } - console.log(option); + console.log("\nUsing options:"); + for (i in option) { + console.log(i + ' = ' + option[i]); + } + console.log("\n"); var parserRaw = fs.readFileSync(__dirname + "/Template.cs", "utf8"); @@ -147,19 +156,19 @@ exec("jison " + process.argv[2], function (error) { for (var i in this.symbolsByIndex) { var symbol = this.symbolsByIndex[i]; - result += '\t\t\tvar symbol' + symbol.index + ' = new ParserSymbol("' + symbol.name + '", ' + symbol.index + ');\n'; - this.symbols.push('\t\t\tSymbols.Add(symbol' + symbol.index + ')'); + result += ' var symbol' + symbol.index + ' = new ParserSymbol("' + symbol.name + '", ' + symbol.index + ');\n'; + this.symbols.push(' Symbols.Add(symbol' + symbol.index + ')'); } - result += '\n\n\t\t\tSymbols = new ParserSymbols();\n'; + result += '\n\n Symbols = new ParserSymbols();\n'; result += this.symbols.join(';\n') + ';\n\n'; for (var i in terminals) { - this.terminals.push('\t\t\t\t\t{' + i + ', symbol' + i + '}'); + this.terminals.push(' {' + i + ', symbol' + i + '}'); } - result += '\t\t\tTerminals = new Dictionary\n\t\t\t\t{\n' + this.terminals.join(',\n') + '\n\t\t\t\t};\n\n'; + result += ' Terminals = new Dictionary\n {\n' + this.terminals.join(',\n') + '\n };\n\n'; for (var i in table) { var items = []; @@ -170,50 +179,50 @@ exec("jison " + process.argv[2], function (error) { if (item.join) { //is array if (item.length == 1) { action = item[0]; - items.push('\t\t\t\t\t{' + j + ', new ParserAction(' + actions[action] + ')}'); + items.push(' {' + j + ', new ParserAction(' + actions[action] + ')}'); } else { action = item[0]; state = item[1]; - items.push('\t\t\t\t\t{' + j + ', new ParserAction(' + actions[action] + ', ref table' + state + ')}'); + items.push(' {' + j + ', new ParserAction(' + actions[action] + ', ref table' + state + ')}'); } } else { state = item; - items.push('\t\t\t\t\t{' + j + ', new ParserAction(' + actions[action] + ', ref table' + state + ')}'); + items.push(' {' + j + ', new ParserAction(' + actions[action] + ', ref table' + state + ')}'); } } - this.tableInstantiation.push('\t\t\tvar table' + i + ' = new ParserState(' + i + ')'); - this.tableDefinition.push('\t\t\tvar tableDefinition' + i + ' = new Dictionary\n\t\t\t\t{\n' + items.join(',\n') + '\n\t\t\t\t}'); - this.tableSetActions.push('\t\t\ttable' + i + '.SetActions(ref tableDefinition' + i + ')'); - this.table.push('\t\t\t\t\t{' + i + ', table' + i + '}'); + this.tableInstantiation.push(' var table' + i + ' = new ParserState(' + i + ')'); + this.tableDefinition.push(' var tableDefinition' + i + ' = new Dictionary\n {\n' + items.join(',\n') + '\n }'); + this.tableSetActions.push(' table' + i + '.SetActions(ref tableDefinition' + i + ')'); + this.table.push(' {' + i + ', table' + i + '}'); } result += this.tableInstantiation.join(';\n') + ';\n\n'; result += this.tableDefinition.join(';\n\n') + ';\n\n'; result += this.tableSetActions.join(';\n') + ';\n\n'; - result += '\t\t\tTable = new Dictionary\n\t\t\t\t{\n' + this.table.join(',\n') + '\n\t\t\t\t};\n\n'; + result += ' Table = new Dictionary\n {\n' + this.table.join(',\n') + '\n };\n\n'; for (var i in defaultActions) { var action = defaultActions[i][0]; var state = defaultActions[i][1]; - this.defaultActions.push('\t\t\t\t\t{' + i + ', new ParserAction(' + actions[action] +', ref table' + state + ')}'); + this.defaultActions.push(' {' + i + ', new ParserAction(' + actions[action] +', ref table' + state + ')}'); } - result += '\t\t\tDefaultActions = new Dictionary\n\t\t\t\t{\n' + this.defaultActions.join(',\n') + '\n\t\t\t\t};\n\n'; + result += ' DefaultActions = new Dictionary\n {\n' + this.defaultActions.join(',\n') + '\n };\n\n'; for (var i in productions) { var production = productions[i]; if (production.join) { var symbol = production[0], len = production[1]; - this.productions.push('\t\t\t\t\t{' + i + ', new ParserProduction(symbol' + this.symbolsByIndex[symbol].index + ',' + len + ')}'); + this.productions.push(' {' + i + ', new ParserProduction(symbol' + this.symbolsByIndex[symbol].index + ',' + len + ')}'); } else { var symbol = production; - this.productions.push('\t\t\t\t\t{' + i + ', new ParserProduction(symbol' + this.symbolsByIndex[symbol].index + ')}'); + this.productions.push(' {' + i + ', new ParserProduction(symbol' + this.symbolsByIndex[symbol].index + ')}'); } } - result += '\t\t\tProductions = new Dictionary\n\t\t\t\t{\t\t\t\t\n' + this.productions.join(',\n') + '\n\t\t\t\t};\n\n\n'; + result += ' Productions = new Dictionary\n { \n' + this.productions.join(',\n') + '\n };\n\n\n'; return result; } @@ -224,16 +233,16 @@ exec("jison " + process.argv[2], function (error) { this.conditions = []; for (var i in rules) { - this.rules.push('\t\t\t\t\t{' + i + ', new Regex(@"' + rules[i].substring(1, rules[i].length - 1).replace(/"/g, '""') + '")}'); + this.rules.push(' {' + i + ', new Regex(@"\\G' + rules[i].substring(2, rules[i].length - 1).replace(/"/g, '""') + '")}'); } - result += '\t\t\tRules = new Dictionary\n\t\t\t\t{\n' + this.rules.join(',\n') + '\n\t\t\t\t};\n\n'; + result += ' Rules = new Dictionary\n {\n' + this.rules.join(',\n') + '\n };\n\n'; for (var i in conditions) { - this.conditions.push('\t\t\t\t\t{"' + i + '", new LexerConditions(new List { ' + conditions[i].rules.join(',') + ' }, ' + conditions[i].inclusive + ')}'); + this.conditions.push(' {"' + i + '", new LexerConditions(new List { ' + conditions[i].rules.join(',') + ' }, ' + conditions[i].inclusive + ')}'); } - result += '\t\t\tConditions = new Dictionary\n\t\t\t\t{\n' + this.conditions.join(',\n') + '\n\t\t\t\t};\n\n'; + result += ' Conditions = new Dictionary\n {\n' + this.conditions.join(',\n') + '\n };\n\n'; return result; } @@ -242,6 +251,7 @@ exec("jison " + process.argv[2], function (error) { .replace(new RegExp('//@@USING_INJECT@@', 'g'),(option.using ? 'using ' + option.using.split(',').join(';\nusing ') + ';' : '')) .replace(new RegExp('[/][*][*][/]namespace Jison[/][*][*][/]', 'g'), 'namespace ' + option.namespace) .replace(new RegExp('[/][*][*][/]class Parser[/][*][*][/]', 'g'), 'class ' + option.class) + .replace(new RegExp('[/][*][*]extends[*][*][/]', 'g'), (option.extends ? ' : ' + option.extends : '')) .replace(new RegExp('[/][*][*][/]public Parser[/][*][*][/]', 'g'), 'public ' + option.class) .replace(new RegExp('[/][*][*][/]ParserValue[/][*][*][/]', 'g'), (option.parserValue || 'ParserValue')) .replace('new Parser(', 'new ' + option.class + '(') diff --git a/ports/csharp/Jison/Jison/formula.js b/ports/csharp/Jison/Jison/formula.js new file mode 100644 index 000000000..e4068a9b4 --- /dev/null +++ b/ports/csharp/Jison/Jison/formula.js @@ -0,0 +1,1305 @@ +/* parser generated by jison 0.4.13 */ +/* + Returns a Parser object of the following structure: + + Parser: { + yy: {} + } + + Parser.prototype: { + yy: {}, + trace: function(), + symbols_: {associative list: name ==> number}, + terminals_: {associative list: number ==> name}, + productions_: [...], + performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$), + table: [...], + defaultActions: {...}, + parseError: function(str, hash), + parse: function(input), + + lexer: { + EOF: 1, + parseError: function(str, hash), + setInput: function(input), + input: function(), + unput: function(str), + more: function(), + less: function(n), + pastInput: function(), + upcomingInput: function(), + showPosition: function(), + test_match: function(regex_match_array, rule_index), + next: function(), + lex: function(), + begin: function(condition), + popState: function(), + _currentRules: function(), + topState: function(), + pushState: function(condition), + + options: { + ranges: boolean (optional: true ==> token location info will include a .range[] member) + flex: boolean (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match) + backtrack_lexer: boolean (optional: true ==> lexer regexes are tested in order and for each matching regex the action code is invoked; the lexer terminates the scan when a token is returned by the action code) + }, + + performAction: function(yy, yy_, $avoiding_name_collisions, YY_START), + rules: [...], + conditions: {associative list: name ==> set}, + } + } + + + token location info (@$, _$, etc.): { + first_line: n, + last_line: n, + first_column: n, + last_column: n, + range: [start_number, end_number] (where the numbers are indexes into the input string, regular zero-based) + } + + + the parseError function receives a 'hash' object with these members for lexer and parser errors: { + text: (matched text) + token: (the produced terminal token, if any) + line: (yylineno) + } + while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: { + loc: (yylloc) + expected: (string describing the set of expected tokens) + recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error) + } +*/ +var formula = (function(){ +var parser = {trace: function trace() { }, +yy: {}, +symbols_: {"error":2,"expressions":3,"expression":4,"EOF":5,"variableSequence":6,"TIME_AMPM":7,"TIME_24":8,"number":9,"STRING":10,"=":11,"+":12,"(":13,")":14,"<":15,">":16,"NOT":17,"-":18,"*":19,"/":20,"^":21,"E":22,"FUNCTION":23,"expseq":24,"cell":25,"FIXEDCELL":26,":":27,"CELL":28,"SHEET":29,"!":30,";":31,",":32,"VARIABLE":33,"DECIMAL":34,"NUMBER":35,"%":36,"#":37,"$accept":0,"$end":1}, +terminals_: {5:"EOF",7:"TIME_AMPM",8:"TIME_24",10:"STRING",11:"=",12:"+",13:"(",14:")",15:"<",16:">",17:"NOT",18:"-",19:"*",20:"/",21:"^",22:"E",23:"FUNCTION",26:"FIXEDCELL",27:":",28:"CELL",29:"SHEET",30:"!",31:";",32:",",33:"VARIABLE",34:"DECIMAL",35:"NUMBER",36:"%",37:"#"}, +productions_: [0,[3,2],[4,1],[4,1],[4,1],[4,1],[4,1],[4,3],[4,3],[4,3],[4,4],[4,4],[4,4],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,2],[4,2],[4,1],[4,3],[4,4],[4,1],[4,1],[4,2],[25,1],[25,3],[25,1],[25,3],[25,3],[25,5],[24,1],[24,3],[24,3],[6,1],[6,3],[9,1],[9,3],[9,2],[2,3],[2,4]], +performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) { +/* this == yyval */ + +var $0 = $$.length - 1; +switch (yystate) { +case 1:return $$[$0-1]; +break; +case 2: + //js + this.$ = yy.handler.variable.apply(yy.obj, $$[$0]); + + //php this.$ = $this->variable($$[$0]); + + /*cs + this.$ = $$[$0]; + */ + +break; +case 3: + //js + this.$ = yy.handler.time.apply(yy.obj, [$$[$0], true]); + // + +break; +case 4: + //js + this.$ = yy.handler.time.apply(yy.obj, [$$[$0]]); + // + +break; +case 5: + //js + this.$ = yy.handler.number.apply(yy.obj, [$$[$0]]); + + //php this.$ = $$[$0] * 1; + + /*cs + $$[$0].ToDouble(); + this.$ = $$[$0]; + */ + +break; +case 6: + //js + this.$ = $$[$0].substring(1, $$[$0].length - 1); + + //php this.$ = substr($$[$0], 1, -1); + + /*cs + $$[$0].ToString(); + this.$ = $$[$0]; + */ + +break; +case 7: + //js + yy.obj.html.pop(); + this.$ = yy.handler.callFunction.apply(yy.obj, ['EQUAL', [$$[$0-2], $$[$0]]]); + + //php this.$ = $$[$0-2] == $$[$0]; + + /*cs + $$[$0-2].Set($$[$0-2].Text == $$[$0].Text); + this.$ = $$[$0-2]; + */ + +break; +case 8: + //js + this.$ = yy.handler.performMath.apply(yy.obj, ['+', $$[$0-2], $$[$0]]); + yy.obj.html.pop(); + yy.obj.html.pop(); + yy.obj.html.push(null); + + /*php + if (is_numeric($$[$0-2]) && is_numeric($$[$0])) { + this.$ = $$[$0-2] + $$[$0]; + } else { + this.$ = $$[$0-2] . $$[$0]; + } + */ + + /*cs + if ($$[$0-2].IsNumeric()) { + $$[$0-2].ToDouble(); + $$[$0-2].Add($$[$0]); + this.$ = $$[$0-2]; + } else { + $$[$0-2].ToString(); + $$[$0-2].Concat($$[$0]); + this.$ = $$[$0-2]; + } + */ + +break; +case 9: + //js + this.$ = yy.handler.number.apply(yy.obj, [$$[$0-1]]); + // + +break; +case 10: + //js + this.$ = yy.handler.callFunction.apply(yy.obj, ['LESS_EQUAL', [$$[$0-3], $$[$0-1]]]); + + //php this.$ = ($$[$0-3] * 1) <= ($$[$0] * 1); + + /*cs + $$[$0-3].Set($$[$0-3].ToDouble() <= $$[$0].ToDouble()); + this.$ = $$[$0-3]; + */ + +break; +case 11: + //js + this.$ = yy.handler.callFunction.apply(yy.obj, ['GREATER_EQUAL', [$$[$0-3], $$[$0-1]]]); + + //php this.$ = ($$[$0-3] * 1) >= ($$[$0] * 1); + + /*cs + $$[$0-3].Set($$[$0-3].ToDouble() >= $$[$0].ToDouble()); + this.$ = $$[$0-3]; + */ + +break; +case 12: + //js|php + this.$ = ($$[$0-3] * 1) != ($$[$0] * 1); + + //js + if (isNaN(this.$)) this.$ = 0; + yy.obj.html.pop(); + yy.obj.html.pop(); + yy.obj.html.push(null); + // + + /*cs + $$[$0-3].Set($$[$0-3].Text != $$[$0].Text); + this.$ = $$[$0-3]; + */ + +break; +case 13: + //js|php + this.$ = $$[$0-2] != $$[$0]; + + //js + yy.obj.html.pop(); + yy.obj.html.pop(); + yy.obj.html.push(null); + // + + /*cs + $$[$0-2].Set($$[$0-2].Text != $$[$0].Text); + this.$ = $$[$0-2]; + */ + +break; +case 14: + //js + this.$ = yy.handler.callFunction.apply(yy.obj, ['GREATER', [$$[$0-2], $$[$0]]]); + + //php this.$ = ($$[$0-2] * 1) > ($$[$0] * 1); + + /*cs + $$[$0-2].Set($$[$0-2].ToDouble() > $$[$0].ToDouble()); + this.$ = $$[$0-2]; + */ + +break; +case 15: + //js + this.$ = yy.handler.callFunction.apply(yy.obj, ['LESS', [$$[$0-2], $$[$0]]]); + + //php this.$ = ($$[$0-2] * 1) < ($$[$0] * 1); + + /*cs + $$[$0-2].Set($$[$0-2].ToDouble() < $$[$0].ToDouble()); + this.$ = $$[$0-2]; + */ + +break; +case 16: + //js|php + this.$ = ($$[$0-2] * 1) - ($$[$0] * 1); + + //js + this.$ = yy.handler.performMath.apply(yy.obj, ['-', $$[$0-2], $$[$0]]); + yy.obj.html.pop(); + yy.obj.html.pop(); + yy.obj.html.push(null); + + /*cs + $$[$0-2].Set($$[$0-2].ToDouble() - $$[$0].ToDouble()); + this.$ = $$[$0-2]; + */ + +break; +case 17: + //js + this.$ = yy.handler.performMath.apply(yy.obj, ['*', $$[$0-2], $$[$0]]); + yy.obj.html.pop(); + yy.obj.html.pop(); + yy.obj.html.push(null); + + //php this.$ = ($$[$0-2] * 1) * ($$[$0] * 1); + + /*cs + $$[$0-2].Set($$[$0-2].ToDouble() * $$[$0].ToDouble()); + this.$ = $$[$0-2]; + */ + +break; +case 18: + //js + this.$ = yy.handler.performMath.apply(yy.obj, ['/', $$[$0-2], $$[$0]]); + yy.obj.html.pop(); + yy.obj.html.pop(); + yy.obj.html.push(null); + + //php this.$ = ($$[$0-2] * 1) / ($$[$0] * 1); + + /*cs + $$[$0-2].Set($$[$0-2].ToDouble() / $$[$0].ToDouble()); + this.$ = $$[$0-2]; + */ + +break; +case 19: + //js + var n1 = yy.handler.number.apply(yy.obj, [$$[$0-2]]), + n2 = yy.handler.number.apply(yy.obj, [$$[$0]]); + + this.$ = yy.handler.performMath.apply(yy.obj, ['^', $$[$0-2], $$[$0]]); + yy.obj.html.pop(); + yy.obj.html.pop(); + yy.obj.html.push(null); + + //php this.$ = pow(($$[$0-2] * 1), ($$[$0] * 1)); + + /*cs + $$[$0-2].Set(Math.Pow($$[$0-2].ToDouble(), $$[$0].ToDouble())); + this.$ = $$[$0-2]; + */ + +break; +case 20: + //js + var n1 = yy.handler.number.apply(yy.obj, [$$[$0]]); + this.$ = n1 * -1; + if (isNaN(this.$)) this.$ = 0; + + //php this.$ = $$[$0-1] * 1; + + /*cs + $$[$0].Set(-$$[$0].ToDouble()); + this.$ = $$[$0]; + */ + +break; +case 21: + //js + var n1 = yy.handler.number.apply(yy.obj, [$$[$0]]); + this.$ = n1 * 1; + if (isNaN(this.$)) this.$ = 0; + + //php this.$ = $$[$0-1] * 1; + + /*cs + $$[$0].Set($$[$0].ToDouble()); + this.$ = $$[$0]; + */ + +break; +case 22:/*this.$ = Math.E;*/; +break; +case 23: + //js + this.$ = yy.handler.callFunction.apply(yy.obj, [$$[$0-2], '']); + + //php this.$ = $this->callFunction($$[$0-2]); + + /*cs + this.$ = Functions.Call($$[$0-2].Text); + */ + +break; +case 24: + //js + this.$ = yy.handler.callFunction.apply(yy.obj, [$$[$0-3], $$[$0-1]]); + + //php this.$ = $this->callFunction($$[$0-3], $$[$0-1]); + + /*cs + this.$ = Functions.Call($$[$0-3].Text, $$[$0-1]); + */ + +break; +case 28: + //js + this.$ = yy.handler.fixedCellValue.apply(yy.obj, [$$[$0]]); + + //php this.$ = $this->fixedCellValue($$[$0]); + + /*cs + this.$ = Spreadsheet.CellValue(Location.ParseFixed($$[$0].Text)); + */ + +break; +case 29: + //js + this.$ = yy.handler.fixedCellRangeValue.apply(yy.obj, [$$[$0-2], $$[$0]]); + + //php this.$ = $this->fixedCellRangeValue($$[$0-2], $$[$0]); + + /*cs + this.$ = Spreadsheet.CellValue(Location.ParseFixed($$[$0-2].Text), Location.ParseFixed($$[$0].Text)); + */ + +break; +case 30: + //js + this.$ = yy.handler.cellValue.apply(yy.obj, [$$[$0]]); + + //php this.$ = $this->cellValue($$[$0]); + + /*cs + this.$ = Spreadsheet.CellValue(Location.Parse($$[$0].Text)); + */ + +break; +case 31: + //js + this.$ = yy.handler.cellRangeValue.apply(yy.obj, [$$[$0-2], $$[$0]]); + + //php this.$ = $this->cellRangeValue($$[$0-2], $$[$0]); + + /*cs + this.$ = Spreadsheet.CellValue(Location.Parse($$[$0-2].Text), Location.Parse($$[$0].Text)); + */ + +break; +case 32: + //js + this.$ = yy.handler.remoteCellValue.apply(yy.obj, [$$[$0-2], $$[$0]]); + + //php this.$ = $this->remoteCellValue($$[$0-2], $$[$0]); + + /*cs + this.$ = Spreadsheet.CellValue(Location.ParseRemote($$[$0-2].Text, $$[$0].Text)); + */ + +break; +case 33: + //js + this.$ = yy.handler.remoteCellRangeValue.apply(yy.obj, [$$[$0-4], $$[$0-2], $$[$0]]); + + //php this.$ = $this->remoteCellRangeValue($$[$0-4], $$[$0-2], $$[$0]); + + /*cs + this.$ = Spreadsheet.CellValue(Location.ParseRemote($$[$0-4].Text, $$[$0-2].Text), Location.ParseRemote($$[$0-4].Text, $$[$0].Text)); + */ + +break; +case 34: + //js + this.$ = [$$[$0]]; + + //php this.$ = array($$[$0]); + + /*cs + this.$ = $$[$0]; + */ + +break; +case 35: + //js + $$[$0-2].push($$[$0]); + this.$ = $$[$0-2]; + + /*php + $$[$0-2][] = $$[$0]; + this.$ = $$[$0-2]; + */ + + /*cs + $$[$0-2].Push($$[$0]); + this.$ = $$[$0-2]; + */ + +break; +case 36: + //js + $$[$0-2].push($$[$0]); + this.$ = $$[$0-2]; + + /*php + $$[$0-2][] = $$[$0]; + this.$ = $$[$0-2]; + */ + + /*cs + $$[$0-2].Push($$[$0]); + this.$ = $$[$0-2]; + */ + +break; +case 37: + //js + this.$ = [$$[$0]]; + + //php this.$ = array($$[$0]); + + /*cs + this.$ = $$[$0]; + */ + +break; +case 38: + //js + this.$ = ($.isArray($$[$0-2]) ? $$[$0-2] : [$$[$0-2]]); + this.$.push($$[$0]); + + /*php + this.$ = (is_array($$[$0-2]) ? $$[$0-2] : array()); + this.$[] = $$[$0]; + */ + + /*cs + $$[$0-2].Push($$[$0]); + this.$ = $$[$0-2]; + */ + +break; +case 39: + //js|php + this.$ = $$[$0] * 1; + + /*cs + $$[$0].ToDouble(); + this.$ = $$[$0]; + */ + +break; +case 40: + //js + this.$ =($$[$0-2] + '.' + $$[$0]) * 1; + + //php this.$ = $$[$0-2] . '.' . $$[$0]; + + /*cs + $$[$0-2].Text += "." + $$[$0].Text; + $$[$0-2].ToDouble(); + this.$ = $$[$0-2]; + */ + +break; +case 41: + //js + yy.obj.html.push($$[$0-1] + $$[$0]); + + //js|php + this.$ = $$[$0-1] * 0.01; + + /*cs + $$[$0-1].Set($$[$0-1].ToDouble() * 0.01); + this.$ = $$[$0-1]; + */ + +break; +case 42: + //js + this.$ = $$[$0-2] + $$[$0-1] + $$[$0]; + + //php this.$ = $$[$0-2] . $$[$0-1] . $$[$0]; + + /*cs + $$[$0-2].Set($$[$0-2].Text + $$[$0-1].Text + $$[$0].Text); + this.$ = $$[$0-2]; + */ + +break; +case 43: + //js + this.$ = $$[$0-2] + $$[$0-1] + $$[$0]; + + //php this.$ = $$[$0-2] . $$[$0-1] . $$[$0]; + + /*cs + $$[$0-3].Set($$[$0-3].Text + $$[$0-2].Text + $$[$0-1].Text + $$[$0].Text); + this.$ = $$[$0-3]; + */ + +break; +} +}, +table: [{2:14,3:1,4:2,6:3,7:[1,4],8:[1,5],9:6,10:[1,7],12:[1,10],13:[1,8],18:[1,9],22:[1,11],23:[1,12],25:13,26:[1,17],28:[1,18],29:[1,19],33:[1,15],35:[1,16],37:[1,20]},{1:[3]},{5:[1,21],11:[1,22],12:[1,23],15:[1,24],16:[1,25],17:[1,26],18:[1,27],19:[1,28],20:[1,29],21:[1,30]},{5:[2,2],11:[2,2],12:[2,2],14:[2,2],15:[2,2],16:[2,2],17:[2,2],18:[2,2],19:[2,2],20:[2,2],21:[2,2],31:[2,2],32:[2,2],34:[1,31]},{5:[2,3],11:[2,3],12:[2,3],14:[2,3],15:[2,3],16:[2,3],17:[2,3],18:[2,3],19:[2,3],20:[2,3],21:[2,3],31:[2,3],32:[2,3]},{5:[2,4],11:[2,4],12:[2,4],14:[2,4],15:[2,4],16:[2,4],17:[2,4],18:[2,4],19:[2,4],20:[2,4],21:[2,4],31:[2,4],32:[2,4]},{5:[2,5],11:[2,5],12:[2,5],14:[2,5],15:[2,5],16:[2,5],17:[2,5],18:[2,5],19:[2,5],20:[2,5],21:[2,5],31:[2,5],32:[2,5],36:[1,32]},{5:[2,6],11:[2,6],12:[2,6],14:[2,6],15:[2,6],16:[2,6],17:[2,6],18:[2,6],19:[2,6],20:[2,6],21:[2,6],31:[2,6],32:[2,6]},{2:14,4:33,6:3,7:[1,4],8:[1,5],9:6,10:[1,7],12:[1,10],13:[1,8],18:[1,9],22:[1,11],23:[1,12],25:13,26:[1,17],28:[1,18],29:[1,19],33:[1,15],35:[1,16],37:[1,20]},{2:14,4:34,6:3,7:[1,4],8:[1,5],9:6,10:[1,7],12:[1,10],13:[1,8],18:[1,9],22:[1,11],23:[1,12],25:13,26:[1,17],28:[1,18],29:[1,19],33:[1,15],35:[1,16],37:[1,20]},{2:14,4:35,6:3,7:[1,4],8:[1,5],9:6,10:[1,7],12:[1,10],13:[1,8],18:[1,9],22:[1,11],23:[1,12],25:13,26:[1,17],28:[1,18],29:[1,19],33:[1,15],35:[1,16],37:[1,20]},{5:[2,22],11:[2,22],12:[2,22],14:[2,22],15:[2,22],16:[2,22],17:[2,22],18:[2,22],19:[2,22],20:[2,22],21:[2,22],31:[2,22],32:[2,22]},{13:[1,36]},{5:[2,25],11:[2,25],12:[2,25],14:[2,25],15:[2,25],16:[2,25],17:[2,25],18:[2,25],19:[2,25],20:[2,25],21:[2,25],31:[2,25],32:[2,25]},{2:37,5:[2,26],11:[2,26],12:[2,26],14:[2,26],15:[2,26],16:[2,26],17:[2,26],18:[2,26],19:[2,26],20:[2,26],21:[2,26],31:[2,26],32:[2,26],33:[1,38],37:[1,20]},{5:[2,37],11:[2,37],12:[2,37],14:[2,37],15:[2,37],16:[2,37],17:[2,37],18:[2,37],19:[2,37],20:[2,37],21:[2,37],31:[2,37],32:[2,37],34:[2,37],37:[1,39]},{5:[2,39],11:[2,39],12:[2,39],14:[2,39],15:[2,39],16:[2,39],17:[2,39],18:[2,39],19:[2,39],20:[2,39],21:[2,39],31:[2,39],32:[2,39],34:[1,40],36:[2,39]},{5:[2,28],11:[2,28],12:[2,28],14:[2,28],15:[2,28],16:[2,28],17:[2,28],18:[2,28],19:[2,28],20:[2,28],21:[2,28],27:[1,41],31:[2,28],32:[2,28]},{5:[2,30],11:[2,30],12:[2,30],14:[2,30],15:[2,30],16:[2,30],17:[2,30],18:[2,30],19:[2,30],20:[2,30],21:[2,30],27:[1,42],31:[2,30],32:[2,30]},{30:[1,43]},{33:[1,44]},{1:[2,1]},{2:14,4:45,6:3,7:[1,4],8:[1,5],9:6,10:[1,7],12:[1,10],13:[1,8],18:[1,9],22:[1,11],23:[1,12],25:13,26:[1,17],28:[1,18],29:[1,19],33:[1,15],35:[1,16],37:[1,20]},{2:14,4:46,6:3,7:[1,4],8:[1,5],9:6,10:[1,7],12:[1,10],13:[1,8],18:[1,9],22:[1,11],23:[1,12],25:13,26:[1,17],28:[1,18],29:[1,19],33:[1,15],35:[1,16],37:[1,20]},{2:14,4:49,6:3,7:[1,4],8:[1,5],9:6,10:[1,7],11:[1,47],12:[1,10],13:[1,8],16:[1,48],18:[1,9],22:[1,11],23:[1,12],25:13,26:[1,17],28:[1,18],29:[1,19],33:[1,15],35:[1,16],37:[1,20]},{2:14,4:51,6:3,7:[1,4],8:[1,5],9:6,10:[1,7],11:[1,50],12:[1,10],13:[1,8],18:[1,9],22:[1,11],23:[1,12],25:13,26:[1,17],28:[1,18],29:[1,19],33:[1,15],35:[1,16],37:[1,20]},{2:14,4:52,6:3,7:[1,4],8:[1,5],9:6,10:[1,7],12:[1,10],13:[1,8],18:[1,9],22:[1,11],23:[1,12],25:13,26:[1,17],28:[1,18],29:[1,19],33:[1,15],35:[1,16],37:[1,20]},{2:14,4:53,6:3,7:[1,4],8:[1,5],9:6,10:[1,7],12:[1,10],13:[1,8],18:[1,9],22:[1,11],23:[1,12],25:13,26:[1,17],28:[1,18],29:[1,19],33:[1,15],35:[1,16],37:[1,20]},{2:14,4:54,6:3,7:[1,4],8:[1,5],9:6,10:[1,7],12:[1,10],13:[1,8],18:[1,9],22:[1,11],23:[1,12],25:13,26:[1,17],28:[1,18],29:[1,19],33:[1,15],35:[1,16],37:[1,20]},{2:14,4:55,6:3,7:[1,4],8:[1,5],9:6,10:[1,7],12:[1,10],13:[1,8],18:[1,9],22:[1,11],23:[1,12],25:13,26:[1,17],28:[1,18],29:[1,19],33:[1,15],35:[1,16],37:[1,20]},{2:14,4:56,6:3,7:[1,4],8:[1,5],9:6,10:[1,7],12:[1,10],13:[1,8],18:[1,9],22:[1,11],23:[1,12],25:13,26:[1,17],28:[1,18],29:[1,19],33:[1,15],35:[1,16],37:[1,20]},{33:[1,57]},{5:[2,41],11:[2,41],12:[2,41],14:[2,41],15:[2,41],16:[2,41],17:[2,41],18:[2,41],19:[2,41],20:[2,41],21:[2,41],31:[2,41],32:[2,41],36:[2,41]},{11:[1,22],12:[1,23],14:[1,58],15:[1,24],16:[1,25],17:[1,26],18:[1,27],19:[1,28],20:[1,29],21:[1,30]},{5:[2,20],11:[2,20],12:[2,20],14:[2,20],15:[2,20],16:[2,20],17:[2,20],18:[2,20],19:[1,28],20:[1,29],21:[1,30],31:[2,20],32:[2,20]},{5:[2,21],11:[2,21],12:[2,21],14:[2,21],15:[2,21],16:[2,21],17:[2,21],18:[2,21],19:[1,28],20:[1,29],21:[1,30],31:[2,21],32:[2,21]},{2:14,4:61,6:3,7:[1,4],8:[1,5],9:6,10:[1,7],12:[1,10],13:[1,8],14:[1,59],18:[1,9],22:[1,11],23:[1,12],24:60,25:13,26:[1,17],28:[1,18],29:[1,19],33:[1,15],35:[1,16],37:[1,20]},{5:[2,27],11:[2,27],12:[2,27],14:[2,27],15:[2,27],16:[2,27],17:[2,27],18:[2,27],19:[2,27],20:[2,27],21:[2,27],31:[2,27],32:[2,27]},{37:[1,39]},{33:[1,62]},{35:[1,63]},{26:[1,64]},{28:[1,65]},{28:[1,66]},{30:[1,67]},{5:[2,7],11:[2,7],12:[1,23],14:[2,7],15:[1,24],16:[1,25],17:[1,26],18:[1,27],19:[1,28],20:[1,29],21:[1,30],31:[2,7],32:[2,7]},{5:[2,8],11:[2,8],12:[2,8],14:[2,8],15:[2,8],16:[2,8],17:[2,8],18:[2,8],19:[1,28],20:[1,29],21:[1,30],31:[2,8],32:[2,8]},{2:14,4:68,6:3,7:[1,4],8:[1,5],9:6,10:[1,7],12:[1,10],13:[1,8],18:[1,9],22:[1,11],23:[1,12],25:13,26:[1,17],28:[1,18],29:[1,19],33:[1,15],35:[1,16],37:[1,20]},{2:14,4:69,6:3,7:[1,4],8:[1,5],9:6,10:[1,7],12:[1,10],13:[1,8],18:[1,9],22:[1,11],23:[1,12],25:13,26:[1,17],28:[1,18],29:[1,19],33:[1,15],35:[1,16],37:[1,20]},{5:[2,15],11:[2,15],12:[1,23],14:[2,15],15:[2,15],16:[2,15],17:[2,15],18:[1,27],19:[1,28],20:[1,29],21:[1,30],31:[2,15],32:[2,15]},{2:14,4:70,6:3,7:[1,4],8:[1,5],9:6,10:[1,7],12:[1,10],13:[1,8],18:[1,9],22:[1,11],23:[1,12],25:13,26:[1,17],28:[1,18],29:[1,19],33:[1,15],35:[1,16],37:[1,20]},{5:[2,14],11:[2,14],12:[1,23],14:[2,14],15:[2,14],16:[2,14],17:[2,14],18:[1,27],19:[1,28],20:[1,29],21:[1,30],31:[2,14],32:[2,14]},{5:[2,13],11:[2,13],12:[1,23],14:[2,13],15:[1,24],16:[1,25],17:[2,13],18:[1,27],19:[1,28],20:[1,29],21:[1,30],31:[2,13],32:[2,13]},{5:[2,16],11:[2,16],12:[2,16],14:[2,16],15:[2,16],16:[2,16],17:[2,16],18:[2,16],19:[1,28],20:[1,29],21:[1,30],31:[2,16],32:[2,16]},{5:[2,17],11:[2,17],12:[2,17],14:[2,17],15:[2,17],16:[2,17],17:[2,17],18:[2,17],19:[2,17],20:[2,17],21:[1,30],31:[2,17],32:[2,17]},{5:[2,18],11:[2,18],12:[2,18],14:[2,18],15:[2,18],16:[2,18],17:[2,18],18:[2,18],19:[2,18],20:[2,18],21:[1,30],31:[2,18],32:[2,18]},{5:[2,19],11:[2,19],12:[2,19],14:[2,19],15:[2,19],16:[2,19],17:[2,19],18:[2,19],19:[2,19],20:[2,19],21:[2,19],31:[2,19],32:[2,19]},{5:[2,38],11:[2,38],12:[2,38],14:[2,38],15:[2,38],16:[2,38],17:[2,38],18:[2,38],19:[2,38],20:[2,38],21:[2,38],31:[2,38],32:[2,38],34:[2,38]},{5:[2,9],11:[2,9],12:[2,9],14:[2,9],15:[2,9],16:[2,9],17:[2,9],18:[2,9],19:[2,9],20:[2,9],21:[2,9],31:[2,9],32:[2,9]},{5:[2,23],11:[2,23],12:[2,23],14:[2,23],15:[2,23],16:[2,23],17:[2,23],18:[2,23],19:[2,23],20:[2,23],21:[2,23],31:[2,23],32:[2,23]},{14:[1,71],31:[1,72],32:[1,73]},{11:[1,22],12:[1,23],14:[2,34],15:[1,24],16:[1,25],17:[1,26],18:[1,27],19:[1,28],20:[1,29],21:[1,30],31:[2,34],32:[2,34]},{30:[1,74]},{5:[2,40],11:[2,40],12:[2,40],14:[2,40],15:[2,40],16:[2,40],17:[2,40],18:[2,40],19:[2,40],20:[2,40],21:[2,40],31:[2,40],32:[2,40],36:[2,40]},{5:[2,29],11:[2,29],12:[2,29],14:[2,29],15:[2,29],16:[2,29],17:[2,29],18:[2,29],19:[2,29],20:[2,29],21:[2,29],31:[2,29],32:[2,29]},{5:[2,31],11:[2,31],12:[2,31],14:[2,31],15:[2,31],16:[2,31],17:[2,31],18:[2,31],19:[2,31],20:[2,31],21:[2,31],31:[2,31],32:[2,31]},{5:[2,32],11:[2,32],12:[2,32],14:[2,32],15:[2,32],16:[2,32],17:[2,32],18:[2,32],19:[2,32],20:[2,32],21:[2,32],27:[1,75],31:[2,32],32:[2,32]},{5:[2,42],11:[2,42],12:[2,42],14:[2,42],15:[2,42],16:[2,42],17:[2,42],18:[2,42],19:[2,42],20:[2,42],21:[2,42],31:[2,42],32:[2,42],33:[2,42],37:[2,42]},{5:[2,10],11:[2,10],12:[1,23],14:[2,10],15:[2,10],16:[2,10],17:[2,10],18:[1,27],19:[1,28],20:[1,29],21:[1,30],31:[2,10],32:[2,10]},{5:[2,12],11:[2,12],12:[1,23],14:[2,12],15:[2,12],16:[2,12],17:[2,12],18:[1,27],19:[1,28],20:[1,29],21:[1,30],31:[2,12],32:[2,12]},{5:[2,11],11:[2,11],12:[1,23],14:[2,11],15:[2,11],16:[2,11],17:[2,11],18:[1,27],19:[1,28],20:[1,29],21:[1,30],31:[2,11],32:[2,11]},{5:[2,24],11:[2,24],12:[2,24],14:[2,24],15:[2,24],16:[2,24],17:[2,24],18:[2,24],19:[2,24],20:[2,24],21:[2,24],31:[2,24],32:[2,24]},{2:14,4:76,6:3,7:[1,4],8:[1,5],9:6,10:[1,7],12:[1,10],13:[1,8],18:[1,9],22:[1,11],23:[1,12],25:13,26:[1,17],28:[1,18],29:[1,19],33:[1,15],35:[1,16],37:[1,20]},{2:14,4:77,6:3,7:[1,4],8:[1,5],9:6,10:[1,7],12:[1,10],13:[1,8],18:[1,9],22:[1,11],23:[1,12],25:13,26:[1,17],28:[1,18],29:[1,19],33:[1,15],35:[1,16],37:[1,20]},{5:[2,43],11:[2,43],12:[2,43],14:[2,43],15:[2,43],16:[2,43],17:[2,43],18:[2,43],19:[2,43],20:[2,43],21:[2,43],31:[2,43],32:[2,43],33:[2,43],37:[2,43]},{28:[1,78]},{11:[1,22],12:[1,23],14:[2,35],15:[1,24],16:[1,25],17:[1,26],18:[1,27],19:[1,28],20:[1,29],21:[1,30],31:[2,35],32:[2,35]},{11:[1,22],12:[1,23],14:[2,36],15:[1,24],16:[1,25],17:[1,26],18:[1,27],19:[1,28],20:[1,29],21:[1,30],31:[2,36],32:[2,36]},{5:[2,33],11:[2,33],12:[2,33],14:[2,33],15:[2,33],16:[2,33],17:[2,33],18:[2,33],19:[2,33],20:[2,33],21:[2,33],31:[2,33],32:[2,33]}], +defaultActions: {21:[2,1]}, +parseError: function parseError(str, hash) { + if (hash.recoverable) { + this.trace(str); + } else { + throw new Error(str); + } +}, +parse: function parse(input) { + var self = this, + stack = [0], + vstack = [null], // semantic value stack + lstack = [], // location stack + table = this.table, + yytext = '', + yylineno = 0, + yyleng = 0, + recovering = 0, + TERROR = 2, + EOF = 1; + + var args = lstack.slice.call(arguments, 1); + + //this.reductionCount = this.shiftCount = 0; + + this.lexer.setInput(input); + this.lexer.yy = this.yy; + this.yy.lexer = this.lexer; + this.yy.parser = this; + if (typeof this.lexer.yylloc == 'undefined') { + this.lexer.yylloc = {}; + } + var yyloc = this.lexer.yylloc; + lstack.push(yyloc); + + var ranges = this.lexer.options && this.lexer.options.ranges; + + if (typeof this.yy.parseError === 'function') { + this.parseError = this.yy.parseError; + } else { + this.parseError = Object.getPrototypeOf(this).parseError; + } + + function popStack (n) { + stack.length = stack.length - 2 * n; + vstack.length = vstack.length - n; + lstack.length = lstack.length - n; + } + + function lex() { + var token; + token = self.lexer.lex() || EOF; // $end = 1 + // if token isn't its numeric value, convert + if (typeof token !== 'number') { + token = self.symbols_[token] || token; + } + return token; + } + + var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected; + while (true) { + // retreive state number from top of stack + state = stack[stack.length - 1]; + + // use default actions if available + if (this.defaultActions[state]) { + action = this.defaultActions[state]; + } else { + if (symbol === null || typeof symbol == 'undefined') { + symbol = lex(); + } + // read action for current state and first input + action = table[state] && table[state][symbol]; + } + +_handle_error: + // handle parse error + if (typeof action === 'undefined' || !action.length || !action[0]) { + var error_rule_depth; + var errStr = ''; + + // Return the rule stack depth where the nearest error rule can be found. + // Return FALSE when no error recovery rule was found. + function locateNearestErrorRecoveryRule(state) { + var stack_probe = stack.length - 1; + var depth = 0; + + // try to recover from error + for(;;) { + // check for error recovery rule in this state + if ((TERROR.toString()) in table[state]) { + return depth; + } + if (state === 0 || stack_probe < 2) { + return false; // No suitable error recovery rule available. + } + stack_probe -= 2; // popStack(1): [symbol, action] + state = stack[stack_probe]; + ++depth; + } + } + + if (!recovering) { + // first see if there's any chance at hitting an error recovery rule: + error_rule_depth = locateNearestErrorRecoveryRule(state); + + // Report error + expected = []; + for (p in table[state]) { + if (this.terminals_[p] && p > TERROR) { + expected.push("'"+this.terminals_[p]+"'"); + } + } + if (this.lexer.showPosition) { + errStr = 'Parse error on line '+(yylineno+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+expected.join(', ') + ", got '" + (this.terminals_[symbol] || symbol)+ "'"; + } else { + errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " + + (symbol == EOF ? "end of input" : + ("'"+(this.terminals_[symbol] || symbol)+"'")); + } + this.parseError(errStr, { + text: this.lexer.match, + token: this.terminals_[symbol] || symbol, + line: this.lexer.yylineno, + loc: yyloc, + expected: expected, + recoverable: (error_rule_depth !== false) + }); + } else if (preErrorSymbol !== EOF) { + error_rule_depth = locateNearestErrorRecoveryRule(state); + } + + // just recovered from another error + if (recovering == 3) { + if (symbol === EOF || preErrorSymbol === EOF) { + throw new Error(errStr || 'Parsing halted while starting to recover from another error.'); + } + + // discard current lookahead and grab another + yyleng = this.lexer.yyleng; + yytext = this.lexer.yytext; + yylineno = this.lexer.yylineno; + yyloc = this.lexer.yylloc; + symbol = lex(); + } + + // try to recover from error + if (error_rule_depth === false) { + throw new Error(errStr || 'Parsing halted. No suitable error recovery rule available.'); + } + popStack(error_rule_depth); + + preErrorSymbol = (symbol == TERROR ? null : symbol); // save the lookahead token + symbol = TERROR; // insert generic error symbol as new lookahead + state = stack[stack.length-1]; + action = table[state] && table[state][TERROR]; + recovering = 3; // allow 3 real symbols to be shifted before reporting a new error + } + + // this shouldn't happen, unless resolve defaults are off + if (action[0] instanceof Array && action.length > 1) { + throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol); + } + + switch (action[0]) { + case 1: // shift + //this.shiftCount++; + + stack.push(symbol); + vstack.push(this.lexer.yytext); + lstack.push(this.lexer.yylloc); + stack.push(action[1]); // push state + symbol = null; + if (!preErrorSymbol) { // normal execution/no error + yyleng = this.lexer.yyleng; + yytext = this.lexer.yytext; + yylineno = this.lexer.yylineno; + yyloc = this.lexer.yylloc; + if (recovering > 0) { + recovering--; + } + } else { + // error just occurred, resume old lookahead f/ before error + symbol = preErrorSymbol; + preErrorSymbol = null; + } + break; + + case 2: + // reduce + //this.reductionCount++; + + len = this.productions_[action[1]][1]; + + // perform semantic action + yyval.$ = vstack[vstack.length-len]; // default to $$ = $1 + // default location, uses first token for firsts, last for lasts + yyval._$ = { + first_line: lstack[lstack.length-(len||1)].first_line, + last_line: lstack[lstack.length-1].last_line, + first_column: lstack[lstack.length-(len||1)].first_column, + last_column: lstack[lstack.length-1].last_column + }; + if (ranges) { + yyval._$.range = [lstack[lstack.length-(len||1)].range[0], lstack[lstack.length-1].range[1]]; + } + r = this.performAction.apply(yyval, [yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack].concat(args)); + + if (typeof r !== 'undefined') { + return r; + } + + // pop off stack + if (len) { + stack = stack.slice(0,-1*len*2); + vstack = vstack.slice(0, -1*len); + lstack = lstack.slice(0, -1*len); + } + + stack.push(this.productions_[action[1]][0]); // push nonterminal (reduce) + vstack.push(yyval.$); + lstack.push(yyval._$); + // goto new state = table[STATE][NONTERMINAL] + newState = table[stack[stack.length-2]][stack[stack.length-1]]; + stack.push(newState); + break; + + case 3: + // accept + return true; + } + + } + + return true; +}}; + +if (typeof(window) !== 'undefined') { + window.Formula = function(handler) { + var formulaLexer = function () {}; + formulaLexer.prototype = formula.lexer; + + var formulaParser = function () { + this.lexer = new formulaLexer(); + this.yy = {}; + }; + + formulaParser.prototype = formula; + var newParser = new formulaParser; + newParser.setObj = function(obj) { + newParser.yy.obj = obj; + }; + newParser.yy.handler = handler; + return newParser; + }; +}/* generated by jison-lex 0.2.1 */ +var lexer = (function(){ +var lexer = { + +EOF:1, + +parseError:function parseError(str, hash) { + if (this.yy.parser) { + this.yy.parser.parseError(str, hash); + } else { + throw new Error(str); + } + }, + +// resets the lexer, sets new input +setInput:function (input) { + this._input = input; + this._more = this._backtrack = this.done = false; + this.yylineno = this.yyleng = 0; + this.yytext = this.matched = this.match = ''; + this.conditionStack = ['INITIAL']; + this.yylloc = { + first_line: 1, + first_column: 0, + last_line: 1, + last_column: 0 + }; + if (this.options.ranges) { + this.yylloc.range = [0,0]; + } + this.offset = 0; + return this; + }, + +// consumes and returns one char from the input +input:function () { + var ch = this._input[0]; + this.yytext += ch; + this.yyleng++; + this.offset++; + this.match += ch; + this.matched += ch; + var lines = ch.match(/(?:\r\n?|\n).*/g); + if (lines) { + this.yylineno++; + this.yylloc.last_line++; + } else { + this.yylloc.last_column++; + } + if (this.options.ranges) { + this.yylloc.range[1]++; + } + + this._input = this._input.slice(1); + return ch; + }, + +// unshifts one char (or a string) into the input +unput:function (ch) { + var len = ch.length; + var lines = ch.split(/(?:\r\n?|\n)/g); + + this._input = ch + this._input; + this.yytext = this.yytext.substr(0, this.yytext.length - len - 1); + //this.yyleng -= len; + this.offset -= len; + var oldLines = this.match.split(/(?:\r\n?|\n)/g); + this.match = this.match.substr(0, this.match.length - 1); + this.matched = this.matched.substr(0, this.matched.length - 1); + + if (lines.length - 1) { + this.yylineno -= lines.length - 1; + } + var r = this.yylloc.range; + + this.yylloc = { + first_line: this.yylloc.first_line, + last_line: this.yylineno + 1, + first_column: this.yylloc.first_column, + last_column: lines ? + (lines.length === oldLines.length ? this.yylloc.first_column : 0) + + oldLines[oldLines.length - lines.length].length - lines[0].length : + this.yylloc.first_column - len + }; + + if (this.options.ranges) { + this.yylloc.range = [r[0], r[0] + this.yyleng - len]; + } + this.yyleng = this.yytext.length; + return this; + }, + +// When called from action, caches matched text and appends it on next action +more:function () { + this._more = true; + return this; + }, + +// When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead. +reject:function () { + if (this.options.backtrack_lexer) { + this._backtrack = true; + } else { + return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), { + text: "", + token: null, + line: this.yylineno + }); + + } + return this; + }, + +// retain first n characters of the match +less:function (n) { + this.unput(this.match.slice(n)); + }, + +// displays already matched input, i.e. for error messages +pastInput:function () { + var past = this.matched.substr(0, this.matched.length - this.match.length); + return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, ""); + }, + +// displays upcoming input, i.e. for error messages +upcomingInput:function () { + var next = this.match; + if (next.length < 20) { + next += this._input.substr(0, 20-next.length); + } + return (next.substr(0,20) + (next.length > 20 ? '...' : '')).replace(/\n/g, ""); + }, + +// displays the character position where the lexing error occurred, i.e. for error messages +showPosition:function () { + var pre = this.pastInput(); + var c = new Array(pre.length + 1).join("-"); + return pre + this.upcomingInput() + "\n" + c + "^"; + }, + +// test the lexed token: return FALSE when not a match, otherwise return token +test_match:function (match, indexed_rule) { + var token, + lines, + backup; + + if (this.options.backtrack_lexer) { + // save context + backup = { + yylineno: this.yylineno, + yylloc: { + first_line: this.yylloc.first_line, + last_line: this.last_line, + first_column: this.yylloc.first_column, + last_column: this.yylloc.last_column + }, + yytext: this.yytext, + match: this.match, + matches: this.matches, + matched: this.matched, + yyleng: this.yyleng, + offset: this.offset, + _more: this._more, + _input: this._input, + yy: this.yy, + conditionStack: this.conditionStack.slice(0), + done: this.done + }; + if (this.options.ranges) { + backup.yylloc.range = this.yylloc.range.slice(0); + } + } + + lines = match[0].match(/(?:\r\n?|\n).*/g); + if (lines) { + this.yylineno += lines.length; + } + this.yylloc = { + first_line: this.yylloc.last_line, + last_line: this.yylineno + 1, + first_column: this.yylloc.last_column, + last_column: lines ? + lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : + this.yylloc.last_column + match[0].length + }; + this.yytext += match[0]; + this.match += match[0]; + this.matches = match; + this.yyleng = this.yytext.length; + if (this.options.ranges) { + this.yylloc.range = [this.offset, this.offset += this.yyleng]; + } + this._more = false; + this._backtrack = false; + this._input = this._input.slice(match[0].length); + this.matched += match[0]; + token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]); + if (this.done && this._input) { + this.done = false; + } + if (token) { + return token; + } else if (this._backtrack) { + // recover context + for (var k in backup) { + this[k] = backup[k]; + } + return false; // rule action called reject() implying the next rule should be tested instead. + } + return false; + }, + +// return next match in input +next:function () { + if (this.done) { + return this.EOF; + } + if (!this._input) { + this.done = true; + } + + var token, + match, + tempMatch, + index; + if (!this._more) { + this.yytext = ''; + this.match = ''; + } + var rules = this._currentRules(); + for (var i = 0; i < rules.length; i++) { + tempMatch = this._input.match(this.rules[rules[i]]); + if (tempMatch && (!match || tempMatch[0].length > match[0].length)) { + match = tempMatch; + index = i; + if (this.options.backtrack_lexer) { + token = this.test_match(tempMatch, rules[i]); + if (token !== false) { + return token; + } else if (this._backtrack) { + match = false; + continue; // rule action called reject() implying a rule MISmatch. + } else { + // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace) + return false; + } + } else if (!this.options.flex) { + break; + } + } + } + if (match) { + token = this.test_match(match, rules[index]); + if (token !== false) { + return token; + } + // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace) + return false; + } + if (this._input === "") { + return this.EOF; + } else { + return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), { + text: "", + token: null, + line: this.yylineno + }); + } + }, + +// return next match that has a token +lex:function lex() { + var r = this.next(); + if (r) { + return r; + } else { + return this.lex(); + } + }, + +// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack) +begin:function begin(condition) { + this.conditionStack.push(condition); + }, + +// pop the previously active lexer condition state off the condition stack +popState:function popState() { + var n = this.conditionStack.length - 1; + if (n > 0) { + return this.conditionStack.pop(); + } else { + return this.conditionStack[0]; + } + }, + +// produce the lexer rule set which is active for the currently active lexer condition state +_currentRules:function _currentRules() { + if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) { + return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules; + } else { + return this.conditions["INITIAL"].rules; + } + }, + +// return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available +topState:function topState(n) { + n = this.conditionStack.length - 1 - Math.abs(n || 0); + if (n >= 0) { + return this.conditionStack[n]; + } else { + return "INITIAL"; + } + }, + +// alias for begin(condition) +pushState:function pushState(condition) { + this.begin(condition); + }, + +// return the number of states currently on the stack +stateStackSize:function stateStackSize() { + return this.conditionStack.length; + }, +options: {}, +performAction: function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) { + +var YYSTATE=YY_START; +switch($avoiding_name_collisions) { +case 0:/* skip whitespace */ +break; +case 1:return 10; +break; +case 2:return 10; +break; +case 3:return 23; +break; +case 4:return 7; +break; +case 5:return 8; +break; +case 6: + //js + if (yy.obj.type == 'cell') return 29; + return 33; + + /*php + if ($this->type == 'cell') return 29; + return 33; + */ + + /*cs + return 29; + //return 33; + */ + +break; +case 7: + //js + if (yy.obj.type == 'cell') return 26; + return 33; + + /*php + if ($this->type == 'cell') return 26; + return 33; + */ + + /*cs + return 26; + //return 33; + */ + +break; +case 8: + //js + if (yy.obj.type == 'cell') return 28; + return 33; + + /*php + if ($this->type == 'cell') return 28; + return 33; + */ + + /*cs + return 28; + //return 33; + */ + +break; +case 9:return 23; +break; +case 10:return 33; +break; +case 11:return 33; +break; +case 12:return 35; +break; +case 13:/* skip whitespace */ +break; +case 14:return 34; +break; +case 15:return 27; +break; +case 16:return 31; +break; +case 17:return 32; +break; +case 18:return 19; +break; +case 19:return 20; +break; +case 20:return 18; +break; +case 21:return 12; +break; +case 22:return 21; +break; +case 23:return 13; +break; +case 24:return 14; +break; +case 25:return 16; +break; +case 26:return 15; +break; +case 27:return 17; +break; +case 28:return 22; +break; +case 29:return '"'; +break; +case 30:return "'"; +break; +case 31:return "!"; +break; +case 32:return 11; +break; +case 33:return 36; +break; +case 34:return 37; +break; +case 35:return 5; +break; +} +}, +rules: [/^(?:\s+)/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:[A-Za-z]{1,}[A-Za-z_0-9]+(?=[(]))/,/^(?:([0]?[1-9]|1[0-2])[:][0-5][0-9]([:][0-5][0-9])?[ ]?(AM|am|aM|Am|PM|pm|pM|Pm))/,/^(?:([0]?[0-9]|1[0-9]|2[0-3])[:][0-5][0-9]([:][0-5][0-9])?)/,/^(?:SHEET[0-9]+)/,/^(?:\$[A-Za-z]+\$[0-9]+)/,/^(?:[A-Za-z]+[0-9]+)/,/^(?:[A-Za-z]+(?=[(]))/,/^(?:[A-Za-z]{1,}[A-Za-z_0-9]+)/,/^(?:[A-Za-z_]+)/,/^(?:[0-9]+)/,/^(?:\\s)/,/^(?:[.])/,/^(?::)/,/^(?:;)/,/^(?:,)/,/^(?:\*)/,/^(?:\/)/,/^(?:-)/,/^(?:\+)/,/^(?:\^)/,/^(?:\()/,/^(?:\))/,/^(?:>)/,/^(?:<)/,/^(?:NOT\b)/,/^(?:E\b)/,/^(?:")/,/^(?:')/,/^(?:!)/,/^(?:=)/,/^(?:%)/,/^(?:[#])/,/^(?:$)/], +conditions: {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35],"inclusive":true}} +}; +return lexer; +})(); +parser.lexer = lexer; +function Parser () { + this.yy = {}; +} +Parser.prototype = parser;parser.Parser = Parser; +return new Parser; +})(); + + +if (typeof require !== 'undefined' && typeof exports !== 'undefined') { +exports.parser = formula; +exports.Parser = formula.Parser; +exports.parse = function () { return formula.parse.apply(formula, arguments); }; +exports.main = function commonjsMain(args) { + if (!args[1]) { + console.log('Usage: '+args[0]+' FILE'); + process.exit(1); + } + var source = require('fs').readFileSync(require('path').normalize(args[1]), "utf8"); + return exports.parser.parse(source); +}; +if (typeof module !== 'undefined' && require.main === module) { + exports.main(process.argv.slice(1)); +} +} \ No newline at end of file diff --git a/ports/php/php.js b/ports/php/php.js index 5e9f84254..d44ca6ebd 100644 --- a/ports/php/php.js +++ b/ports/php/php.js @@ -1,268 +1,267 @@ -var fs = require('fs'), - util = require('util'), - exec = require('child_process').exec, - path = require('path'); - -GLOBAL.convertToSyntax = function (types, body) { - if (types['php'] || types['PHP']) { - return body; - } - return ''; +GLOBAL.convertToSyntax = function (types, body) { + if (types['php'] || types['PHP']) { + return body; + } + return ''; }; -function puts(error, stdout, stderr) { - util.puts(stdout); -} - -console.log("Executing: " + "jison " + process.argv[2]); - -exec("jison " + process.argv[2], function (error) { - if (error) { - console.log(error); - return; - } - - String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g, '');}; - - var fileName = process.argv[2].replace('.jison', ''), - comments = require(path.resolve(__dirname, '../comments.js')), - requirePath = path.resolve(process.argv[2]).replace('.jison', '') + '.js'; - - console.log("Opening newly created jison js file: " + fileName + '.js'); - - var Parser = require(requirePath), - symbols = Parser.parser.symbols_, - terminals = Parser.parser.terminals_, - productions = Parser.parser.productions_, - table = Parser.parser.table, - defaultActions = Parser.parser.defaultActions, - //turn regex into string - rules = []; - - for (var i = 0; i < Parser.parser.lexer.rules.length; i++) { - rules.push(Parser.parser.lexer.rules[i].toString()); - } - - var conditions = Parser.parser.lexer.conditions, - options = Parser.parser.lexer.options, - parserPerformAction = Parser.parser.performAction.toString(), - lexerPerformAction = Parser.parser.lexer.performAction.toString(); - - function jsFnBody(str) { - str = str.split('{'); - str.shift(); - str = str.join('{'); - - str = str.split('}'); - str.pop(); - str = str.join('}'); - - return str; - } - - function jsPerformActionToPhp(str) { - str = jsFnBody(str); - str = str.replace("var $0 = $$.length - 1;", ''); - str = str.replace("var YYSTATE=YY_START", ''); - str = str.replace(new RegExp('[$]0', 'g'), '$o'); - str = str.replace(new RegExp('[$][$]', 'g'), '$s'); - str = str.replace(new RegExp('default[:][;]', 'g'), ''); - str = str.replace(new RegExp('this[.][$]', 'g'), '$thisS'); - str = str.replace(new RegExp('this[-][>]', 'g'), '$this->'); - str = str.replace(new RegExp('yystate', 'g'), '$yystate'); - //str = str.replace(new RegExp('yytext', 'g'), 'yy->text'); - str = str.replace(new RegExp('[$]yy[_][.]', 'g'), '$this->yy->'); - str = str.replace(new RegExp('[$]this[-][>]yy[-][>]yy', 'g'), '$this->yy->'); - str = str.replace(new RegExp('[.]yytext', 'g'), '->text'); - str = str.replace(new RegExp('yy[.]', 'g'), 'yy->'); - str = str.replace(new RegExp('yy_[.][$]', 'g'), '$this->yy->'); - str = str.replace(new RegExp('[$]accept', 'g'), 'accept'); - str = str.replace(new RegExp('[$]end', 'g'), 'end'); - str = str.replace(new RegExp('console[.]log'), ''); - str = str.replace(new RegExp('[$]avoiding_name_collisions'), '$avoidingNameCollisions'); - - str = comments.parse(str); - - str = str.replace(/(\d)\n/g, function () { - return arguments[1] + ';\n'; - }); - - return str; - } - - - var option = { - 'namespace': 'Jison', - 'class': fileName, - 'fileName': fileName + '.php', - 'extends': '', - 'use': '', - 'parserValue': '' - }; - - var parserDefinition = fs.readFileSync(fileName + '.jison', "utf8"); - parserDefinition = parserDefinition.split(/\n/g); - for(var i = 0; i < parserDefinition.length; i++) { - if (parserDefinition[i].match('//option')) { - parserDefinition[i] = parserDefinition[i].replace('//option ', ''); - parserDefinition[i] = parserDefinition[i].split(':'); - option[parserDefinition[i][0]] = parserDefinition[i][1]; - } - } - - console.log(option); - - var parserRaw = fs.readFileSync(__dirname + "/template.php", "utf8"); - - function parserInject() { - var result = '\n'; - this.symbols = []; - this.symbolsByIndex = []; - this.tableInstantiation = []; - this.tableDefinition = []; - this.tableSetActions = []; - this.table = []; - this.terminals = []; - this.defaultActions = []; - this.productions = []; - - var actions = [ - 'none', - 'shift', - 'reduce', - 'accept' - ]; - - for (var i in symbols) { - this.symbolsByIndex[symbols[i] * 1] = { - name: i.replace('$', ''), - index: symbols[i] - }; +var fs = require('fs'), + spawn = require('child_process').spawn, + path = require('path'), + createPHPFile = function (jisonFileName) { + String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g, '');}; + + var fileName = jisonFileName.replace('.jison', ''), + comments = require(path.resolve(__dirname, '../comments.js')), + requirePath = path.resolve(jisonFileName).replace('.jison', '') + '.js'; + + console.log("\n\n\nOpening newly created jison js file: " + fileName + '.js'); + + var Parser = require(requirePath), + symbols = Parser.parser.symbols_, + terminals = Parser.parser.terminals_, + productions = Parser.parser.productions_, + table = Parser.parser.table, + defaultActions = Parser.parser.defaultActions, + //turn regex into string + rules = []; + + for (var i = 0; i < Parser.parser.lexer.rules.length; i++) { + rules.push(Parser.parser.lexer.rules[i].toString()); } - console.log(this.symbolsByIndex); + var conditions = Parser.parser.lexer.conditions, + options = Parser.parser.lexer.options, + parserPerformAction = Parser.parser.performAction.toString(), + lexerPerformAction = Parser.parser.lexer.performAction.toString(); + + function jsFnBody(str) { + str = str.split('{'); + str.shift(); + str = str.join('{'); - for (var i in this.symbolsByIndex) { - var symbol = this.symbolsByIndex[i]; - result += '\t\t\t$symbol' + symbol.index + ' = new ParserSymbol("' + symbol.name + '", ' + symbol.index + ');\n'; - this.symbols.push('\t\t\t$this->symbols[' + symbol.index + '] = $symbol' + symbol.index + ''); - this.symbols.push('\t\t\t$this->symbols["' + symbol.name + '"] = $symbol' + symbol.index + ''); + str = str.split('}'); + str.pop(); + str = str.join('}'); + return str; + } + + function jsPerformActionToPhp(str) { + str = jsFnBody(str); + str = str.replace("var $0 = $$.length - 1;", ''); + str = str.replace("var YYSTATE=YY_START", ''); + str = str.replace(new RegExp('[$]0', 'g'), '$o'); + str = str.replace(new RegExp('[$][$]', 'g'), '$s'); + str = str.replace(new RegExp('default[:][;]', 'g'), ''); + str = str.replace(new RegExp('this[.][$]', 'g'), '$thisS'); + str = str.replace(new RegExp('this[-][>]', 'g'), '$this->'); + str = str.replace(new RegExp('yystate', 'g'), '$yystate'); + //str = str.replace(new RegExp('yytext', 'g'), 'yy->text'); + str = str.replace(new RegExp('[$]yy[_][.]', 'g'), '$this->yy->'); + str = str.replace(new RegExp('[$]this[-][>]yy[-][>]yy', 'g'), '$this->yy->'); + str = str.replace(new RegExp('[.]yytext', 'g'), '->text'); + str = str.replace(new RegExp('yy[.]', 'g'), 'yy->'); + str = str.replace(new RegExp('yy_[.][$]', 'g'), '$this->yy->'); + str = str.replace(new RegExp('[$]accept', 'g'), 'accept'); + str = str.replace(new RegExp('[$]end', 'g'), 'end'); + str = str.replace(new RegExp('console[.]log'), ''); + str = str.replace(new RegExp('[$]avoiding_name_collisions'), '$avoidingNameCollisions'); + + str = comments.parse(str); + + str = str.replace(/(\d)\n/g, function () { + return arguments[1] + ';\n'; + }); + + return str; } - result += this.symbols.join(';\n') + ';\n\n'; - for (var i in terminals) { - this.terminals.push('\t\t\t\t\t' + i + '=>&$symbol' + i + ''); + var option = { + 'namespace': 'Jison', + 'class': fileName, + 'fileName': fileName + '.php', + 'extends': '', + 'use': '', + 'parserValue': '' + }; + + var parserDefinition = fs.readFileSync(fileName + '.jison', "utf8"); + parserDefinition = parserDefinition.split(/\n/g); + for(var i = 0; i < parserDefinition.length; i++) { + if (parserDefinition[i].match('//option')) { + parserDefinition[i] = parserDefinition[i].replace('//option ', ''); + parserDefinition[i] = parserDefinition[i].split(':'); + option[parserDefinition[i][0]] = parserDefinition[i][1]; + } } - result += '\t\t\t$this->terminals = array(\n' + this.terminals.join(',\n') + '\n\t\t\t\t);\n\n'; - - for (var i in table) { - var items = []; - for (var j in table[i]) { - var item = table[i][j], - action = 0, - state = 0; - if (item.join) { //is array - if (item.length == 1) { - action = item[0]; - items.push('\t\t\t\t\t' + j + '=>new ParserAction($this->' + actions[action] + ')'); + var parserRaw = fs.readFileSync(__dirname + "/template.php", "utf8"); + + function parserInject() { + var result = '\n'; + this.symbols = []; + this.symbolsByIndex = []; + this.tableInstantiation = []; + this.tableDefinition = []; + this.tableSetActions = []; + this.table = []; + this.terminals = []; + this.defaultActions = []; + this.productions = []; + + var actions = [ + 'none', + 'shift', + 'reduce', + 'accept' + ]; + + for (var i in symbols) { + this.symbolsByIndex[symbols[i] * 1] = { + name: i.replace('$', ''), + index: symbols[i] + }; + } + + for (var i in this.symbolsByIndex) { + var symbol = this.symbolsByIndex[i]; + result += '\t\t\t$symbol' + symbol.index + ' = new ParserSymbol("' + symbol.name + '", ' + symbol.index + ');\n'; + this.symbols.push('\t\t\t$this->symbols[' + symbol.index + '] = $symbol' + symbol.index + ''); + this.symbols.push('\t\t\t$this->symbols["' + symbol.name + '"] = $symbol' + symbol.index + ''); + + } + + result += this.symbols.join(';\n') + ';\n\n'; + + for (var i in terminals) { + this.terminals.push('\t\t\t\t\t' + i + '=>&$symbol' + i + ''); + } + + result += '\t\t\t$this->terminals = array(\n' + this.terminals.join(',\n') + '\n\t\t\t\t);\n\n'; + + for (var i in table) { + var items = []; + for (var j in table[i]) { + var item = table[i][j], + action = 0, + state = 0; + if (item.join) { //is array + if (item.length == 1) { + action = item[0]; + items.push('\t\t\t\t\t' + j + '=>new ParserAction($this->' + actions[action] + ')'); + } else { + action = item[0]; + state = item[1]; + items.push('\t\t\t\t\t' + j + '=>new ParserAction($this->' + actions[action] + ', $table' + state + ')'); + } } else { - action = item[0]; - state = item[1]; + state = item; items.push('\t\t\t\t\t' + j + '=>new ParserAction($this->' + actions[action] + ', $table' + state + ')'); } - } else { - state = item; - items.push('\t\t\t\t\t' + j + '=>new ParserAction($this->' + actions[action] + ', $table' + state + ')'); } + + this.tableInstantiation.push('\t\t\t$table' + i + ' = new ParserState(' + i + ')'); + this.tableDefinition.push('\t\t\t$tableDefinition' + i + ' = array(\n\t\t\t\t\n' + items.join(',\n') + '\n\t\t\t\t)'); + this.tableSetActions.push('\t\t\t$table' + i + '->setActions($tableDefinition' + i + ')'); + this.table.push('\t\t\t\t\t' + i + '=>$table' + i + ''); } - this.tableInstantiation.push('\t\t\t$table' + i + ' = new ParserState(' + i + ')'); - this.tableDefinition.push('\t\t\t$tableDefinition' + i + ' = array(\n\t\t\t\t\n' + items.join(',\n') + '\n\t\t\t\t)'); - this.tableSetActions.push('\t\t\t$table' + i + '->setActions($tableDefinition' + i + ')'); - this.table.push('\t\t\t\t\t' + i + '=>$table' + i + ''); - } + result += this.tableInstantiation.join(';\n') + ';\n\n'; + result += this.tableDefinition.join(';\n\n') + ';\n\n'; + result += this.tableSetActions.join(';\n') + ';\n\n'; + result += '\t\t\t$this->table = array(\n\t\t\t\t\n' + this.table.join(',\n') + '\n\t\t\t\t);\n\n'; - result += this.tableInstantiation.join(';\n') + ';\n\n'; - result += this.tableDefinition.join(';\n\n') + ';\n\n'; - result += this.tableSetActions.join(';\n') + ';\n\n'; - result += '\t\t\t$this->table = array(\n\t\t\t\t\n' + this.table.join(',\n') + '\n\t\t\t\t);\n\n'; + for (var i in defaultActions) { + var action = defaultActions[i][0]; + var state = defaultActions[i][1]; + this.defaultActions.push('\t\t\t\t\t' + i + '=>new ParserAction($this->' + actions[action] +', $table' + state + ')'); + } + + result += '\t\t\t$this->defaultActions = array(\n\t\t\t\t\n' + this.defaultActions.join(',\n') + '\n\t\t\t\t);\n\n'; - for (var i in defaultActions) { - var action = defaultActions[i][0]; - var state = defaultActions[i][1]; - this.defaultActions.push('\t\t\t\t\t' + i + '=>new ParserAction($this->' + actions[action] +', $table' + state + ')'); + for (var i in productions) { + var production = productions[i]; + if (production.join) { + var symbol = production[0], + len = production[1]; + this.productions.push('\t\t\t\t\t' + i + '=>new ParserProduction($symbol' + this.symbolsByIndex[symbol].index + ',' + len + ')'); + } else { + var symbol = production; + this.productions.push('\t\t\t\t\t' + i + '=>new ParserProduction($symbol' + this.symbolsByIndex[symbol].index + ')'); + } + } + + result += '\t\t\t$this->productions = array(\n\t\t\t\t\n' + this.productions.join(',\n') + '\n\t\t\t\t);\n\n\n'; + + return result; } - result += '\t\t\t$this->defaultActions = array(\n\t\t\t\t\n' + this.defaultActions.join(',\n') + '\n\t\t\t\t);\n\n'; + function lexerInject() { + var result = '\n'; + this.rules = [], + this.conditions = []; - for (var i in productions) { - var production = productions[i]; - if (production.join) { - var symbol = production[0], - len = production[1]; - this.productions.push('\t\t\t\t\t' + i + '=>new ParserProduction($symbol' + this.symbolsByIndex[symbol].index + ',' + len + ')'); - } else { - var symbol = production; - this.productions.push('\t\t\t\t\t' + i + '=>new ParserProduction($symbol' + this.symbolsByIndex[symbol].index + ')'); + for (var i in rules) { + this.rules.push('\t\t\t\t\t' + i + '=>"/\\G' + rules[i].substring(2, rules[i].length - 1).replace(/"/g, '\\"') + '/"'); } - } - result += '\t\t\t$this->productions = array(\n\t\t\t\t\n' + this.productions.join(',\n') + '\n\t\t\t\t);\n\n\n'; + result += '\t\t\t$this->rules = array(\n\t\t\t\t\n' + this.rules.join(',\n') + '\n\t\t\t\t);\n\n'; - return result; - } + for (var i in conditions) { + this.conditions.push('\t\t\t\t\t"' + i + '"=>new LexerConditions(array( ' + conditions[i].rules.join(',') + '), ' + conditions[i].inclusive + ')'); + } - function lexerInject() { - var result = '\n'; - this.rules = [], - this.conditions = []; + result += '\t\t\t$this->conditions = array(\n\t\t\t\t\n' + this.conditions.join(',\n') + '\n\t\t\t\t);\n\n'; - for (var i in rules) { - this.rules.push('\t\t\t\t\t' + i + '=>"/' + rules[i].substring(1, rules[i].length - 1).replace(/"/g, '\\"') + '/"'); + return result; } - result += '\t\t\t$this->rules = array(\n\t\t\t\t\n' + this.rules.join(',\n') + '\n\t\t\t\t);\n\n'; + parserRaw = parserRaw + .replace('/**/namespace Jison;/**/', (option.namespace ? 'namespace ' + option.namespace + ';\nuse Exception;\n' : '')) + .replace('/**/class Parser/**/', 'class ' + option.class + (option.extends ? ' extends ' + option.extends : '')) + .replace('/**use**/', (option.use ? 'use ' + option.use : '')) + .replace(/[/][*][*][/]ParserValue[/][*][*][/]/g, (option.parserValue ? option.parserValue : 'ParserValue')) - for (var i in conditions) { - this.conditions.push('\t\t\t\t\t"' + i + '"=>new LexerConditions(array( ' + conditions[i].rules.join(',') + '), ' + conditions[i].inclusive + ')'); - } + .replace('//@@PARSER_INJECT@@', + parserInject() + ) - result += '\t\t\t$this->conditions = array(\n\t\t\t\t\n' + this.conditions.join(',\n') + '\n\t\t\t\t);\n\n'; + .replace('//@@LEXER_INJECT@@', + lexerInject() + ) - return result; - } + .replace('//@@ParserPerformActionInjection@@', + jsPerformActionToPhp(parserPerformAction) + ) - parserRaw = parserRaw - .replace('/**/namespace Jison;/**/', (option.namespace ? 'namespace ' + option.namespace + ';\nuse Exception;\n' : '')) - .replace('/**/class Parser/**/', 'class ' + option.class + (option.extends ? ' extends ' + option.extends : '')) - .replace('/**use**/', (option.use ? 'use ' + option.use : '')) - .replace(/[/][*][*][/]ParserValue[/][*][*][/]/g, (option.parserValue ? option.parserValue : 'ParserValue')) - - .replace('//@@PARSER_INJECT@@', - parserInject() - ) - - .replace('//@@LEXER_INJECT@@', - lexerInject() - ) - - .replace('//@@ParserPerformActionInjection@@', - jsPerformActionToPhp(parserPerformAction) - ) - - .replace('//@@LexerPerformActionInjection@@', - jsPerformActionToPhp(lexerPerformAction, true) - ); - - fs.writeFile(option.fileName, parserRaw, function(err) { - if (err) { - console.log("Something went bad"); - } else { - console.log("Success writing new parser files " + fileName + ".js" + " & " + option.fileName); - console.log("Please Note: The php version of the jison parser is only an ATTEMPTED conversion"); - } - }); + .replace('//@@LexerPerformActionInjection@@', + jsPerformActionToPhp(lexerPerformAction, true) + ); + + fs.writeFile(option.fileName, parserRaw, function(err) { + if (err) { + console.log("Something went bad"); + } else { + console.log("**************SUCCESS**************"); + console.log("Success writing new parser files " + fileName + ".js" + " & " + option.fileName); + console.log("Please Note: The php version of the jison parser is only an ATTEMPTED conversion"); + } + }); + }, + msg = (console.log("Executing: " + "jison " + process.argv[2])), + spawnedJison = spawn("jison", [process.argv[2]]); + +spawnedJison.stdout.on('data', function (data) { + console.log(data.toString()); + console.log("**************Possible Issue**************"); +}); + +spawnedJison.on('exit', function(code) { + if (code != 0) { + console.log('Failed: ' + code); + } else { + createPHPFile(process.argv[2]); + } }); \ No newline at end of file diff --git a/ports/php/readme b/ports/php/readme.md similarity index 54% rename from ports/php/readme rename to ports/php/readme.md index 4f7c84d34..c0d30766a 100644 --- a/ports/php/readme +++ b/ports/php/readme.md @@ -1,29 +1,31 @@ -Name: Jison Parser Php Port -Written By: Robert Plummer, RobertLeePlummerJr@gmail.com -Description: A jison wrapper that first processes a jison file and then injects a php template with the variables from a .js file. +# Jison Parser Php Port # +A jison wrapper that first processes a jison file and then injects a php template with the variables from a .js file. Written By: Robert Plummer, RobertLeePlummerJr@gmail.com -DIRECTIONS: +## DIRECTIONS ## 1. After you've downloaded jison & node.js, navigate in command line interface to the folder that contains the ".jison" file that you want to process 2. Process the ".jison" file like this "nodejs /location_of_jison/ports/php/php.js my_jison_file.jison" -CONFIGURATION: +## CONFIGURATION ## Configuration takes advantage of the commenting in javascript so as not to conflict with. -*In your ".jison" file -**A that has a "//js" comment BEFORE the javascript line starts a javascript area of the parser section. Which will be removed from the php. -**A line that simply has "//" ends whatever commenting is currently active. -**A that has a "//php" comment ON the line of php it starts a php area of the parser section. In Javascript this is just a comment, in php though, the comment is removed so that it can be called. -**A that has no comment, is left alone. -*Comments in the ".jison" file that start with "//option" can be used to configure the output of the php file. -**//option optionName:value -**Current Options: -*** "namespace" - default is "Jison" -*** "class" - default is your ".jison" file without the file extension -*** "fileName" - default is your ".jison" file without the file extension followed by ".php" -EXAMPLE: +### In your ".jison" file ### +* A line that has a "//js" comment BEFORE the javascript line starts a javascript area of the parser section. Which will be removed from the php. +* A line that simply has "//" ends whatever commenting is currently active. +* A that has a "//php" comment ON the line of php it starts a php area of the parser section. In Javascript this is just a comment, in php though, the comment is removed so that it can be called. +* A line that has no comment, is left alone. + +### Comments in the ".jison" file that start with "//option" can be used to configure the output of the php file. ### +* //option optionName:value +* Current Options: + * "namespace" - default is "Jison" + * "class" - default is your ".jison" file without the file extension + * "fileName" - default is your ".jison" file without the file extension followed by ".php" + +## EXAMPLE ## +``` contents : content - {$$ = $1;} //<--this is left alone + {$$ = $1;} //<--this is left alone | contents content { //js @@ -41,3 +43,4 @@ contents // } ; +``` diff --git a/ports/php/template.php b/ports/php/template.php index 436b679f4..538e25969 100644 --- a/ports/php/template.php +++ b/ports/php/template.php @@ -17,6 +17,7 @@ public $shift = 1; public $reduce = 2; public $accept = 3; + public $unputStack = array(); function trace() { @@ -203,7 +204,6 @@ function parse($input) public $eof; public $yy = null; public $match = ""; - public $matched = ""; public $conditionStack = array(); public $conditionStackCount = 0; public $rules = array(); @@ -218,7 +218,7 @@ function parse($input) function setInput($input) { - $this->input = $input; + $this->input = new InputReader($input); $this->more = $this->less = $this->done = false; $this->yy = new /**/ParserValue/**/(); $this->conditionStack = array('INITIAL'); @@ -235,12 +235,11 @@ function setInput($input) function input() { - $ch = $this->input[0]; + $ch = $this->input->ch(); $this->yy->text .= $ch; $this->yy->leng++; $this->offset++; $this->match .= $ch; - $this->matched .= $ch; $lines = preg_match("/(?:\r\n?|\n).*/", $ch); if (count($lines) > 0) { $this->yy->lineNo++; @@ -252,30 +251,32 @@ function input() $this->yy->loc->range->y++; } - $this->input = array_slice($this->input, 1); return $ch; } function unput($ch) { + $yy = new /**/ParserValue/**/(); + $len = strlen($ch); $lines = explode("/(?:\r\n?|\n)/", $ch); $linesCount = count($lines); - $this->input = $ch . $this->input; - $this->yy->text = substr($this->yy->text, 0, $len - 1); + $this->input->unCh($len); + $yy->text = substr($this->yy->text, 0, $len - 1); //$this->yylen -= $len; $this->offset -= $len; $oldLines = explode("/(?:\r\n?|\n)/", $this->match); $oldLinesCount = count($oldLines); $this->match = substr($this->match, 0, strlen($this->match) - 1); - $this->matched = substr($this->matched, 0, strlen($this->matched) - 1); - if (($linesCount - 1) > 0) $this->yy->lineNo -= $linesCount - 1; + if (($linesCount - 1) > 0) { + $yy->lineNo = $this->yy->lineNo - $linesCount - 1; + } $r = $this->yy->loc->range; $oldLinesLength = (isset($oldLines[$oldLinesCount - $linesCount]) ? strlen($oldLines[$oldLinesCount - $linesCount]) : 0); - $this->yy->loc = new ParserLocation( + $yy->loc = new ParserLocation( $this->yy->loc->firstLine, $this->yy->lineNo, $this->yy->loc->firstColumn, @@ -286,8 +287,10 @@ function unput($ch) ); if (isset($this->ranges)) { - $this->yy->loc->range = array($r[0], $r[0] + $this->yy->leng - $len); + $yy->loc->range = array($r->x, $r->y + $this->yy->leng - $len); } + + $this->unputStack[] = $yy; } function more() @@ -297,17 +300,22 @@ function more() function pastInput() { - $past = substr($this->matched, 0, strlen($this->matched) - strlen($this->match)); + $matched = $this->input->toString(); + $past = substr($matched, 0, strlen($matched) - strlen($this->match)); return (strlen($past) > 20 ? '...' : '') . preg_replace("/\n/", "", substr($past, -20)); } function upcomingInput() { - $next = $this->match; - if (strlen($next) < 20) { - $next .= substr($this->input, 0, 20 - strlen($next)); + if (!$this->done) { + $next = $this->match; + if (strlen($next) < 20) { + $next .= substr($this->input->toString(), 0, 20 - strlen($next)); + } + return preg_replace("/\n/", "", substr($next, 0, 20) . (strlen($next) > 20 ? '...' : '')); + } else { + return ""; } - return preg_replace("/\n/", "", substr($next, 0, 20) . (strlen($next) > 20 ? '...' : '')); } function showPosition() @@ -324,11 +332,14 @@ function showPosition() function next() { + if ($yy = array_pop($this->unputStack)) { + $this->yy = $yy; + } if ($this->done == true) { return $this->eof; } - if (empty($this->input)) { + if ($this->input->done) { $this->done = true; } @@ -339,7 +350,7 @@ function next() $rules = $this->currentRules(); for ($i = 0, $j = count($rules); $i < $j; $i++) { - preg_match($this->rules[$rules[$i]], $this->input, $tempMatch); + $tempMatch = $this->input->match($this->rules[$rules[$i]]); if ($tempMatch && (empty($match) || count($tempMatch[0]) > count($match[0]))) { $match = $tempMatch; $index = $i; @@ -368,33 +379,32 @@ function next() $this->yy->text .= $match[0]; $this->match .= $match[0]; $this->matches = $match; - $this->matched .= $match[0]; $this->yy->leng = strlen($this->yy->text); if (isset($this->ranges)) { $this->yy->loc->range = new ParserRange($this->offset, $this->offset += $this->yy->leng); } $this->more = false; - $this->input = substr($this->input, $matchCount, strlen($this->input)); + $this->input->addMatch($match[0]); $ruleIndex = $rules[$index]; $nextCondition = $this->conditionStack[$this->conditionStackCount - 1]; $token = $this->lexerPerformAction($ruleIndex, $nextCondition); - if ($this->done == true && empty($this->input) == false) { + if ($this->done == true && !$this->input->done) { $this->done = false; } if (empty($token) == false) { return $this->symbols[ - $token + $token ]; } else { return null; } } - if (empty($this->input)) { + if ($this->input->done) { return $this->eof; } else { $this->lexerError("Lexical error on line " . ($this->yy->lineNo + 1) . ". Unrecognized text.\n" . $this->showPosition(), new LexerError("", -1, $this->yy->lineNo)); @@ -460,7 +470,9 @@ public function Range($range) public function __clone() { - return new ParserLocation($this->firstLine, $this->lastLine, $this->firstColumn, $this->lastColumn); + if (isset($this->range)) { + $this->range = clone $this->range; + } } } @@ -472,14 +484,9 @@ class ParserValue public $text; function __clone() { - $clone = new ParserValue(); - $clone->leng = $this->leng; if (isset($this->loc)) { - $clone->loc = clone $this->loc; + $this->loc = clone $this->loc; } - $clone->lineNo = $this->lineNo; - $clone->text = $this->text; - return $clone; } } @@ -612,4 +619,57 @@ function __construct($x, $y) $this->x = $x; $this->y = $y; } +} + +class InputReader +{ + public $done = false; + public $input; + public $length; + public $matches = array(); + public $position = 0; + + public function __construct($input) + { + $this->input = $input; + $this->length = strlen($input); + } + + public function addMatch($match) { + $this->matches[] = $match; + $this->position += strlen($match); + $this->done = ($this->position >= $this->length); + } + + public function ch() + { + $ch = $this->input{$this->position}; + $this->addMatch($ch); + return $ch; + } + + public function unCh($chLength) + { + $this->position -= $chLength; + $this->position = max(0, $this->position); + $this->done = ($this->position >= $this->length); + } + + public function substring($start, $end) { + $start = ($start != 0 ? $this->position + $start : $this->position); + $end = ($end != 0 ? $start + $end : $this->length); + return substr($this->input, $start, $end); + } + + public function match($rule) { + if (preg_match($rule, $this->input, $match, null, $this->position)) { + return $match; + } + return null; + } + + public function toString() + { + return implode('', $this->matches); + } } \ No newline at end of file