/// <summary> /// FactorTail := Number | '(' Expr ')' | Function /// </summary> void ParseFactorTail(TokenQueue tokens) { Token current = tokens.PeekToken(); if (current.TokenType == TokenType.OpenParenthesis) { current = tokens.NextToken(); ParseExpressionR(tokens); // Skip the closing bracket if (tokens.PeekToken().TokenType != TokenType.CloseParenthesis) { throw new ParserExceptionWithPosistion(string.Format("Expected close bracket at {0}.", current.Position), current.Position); } tokens.NextToken(); } else if (current.TokenType == TokenType.Text && IsRegisteredFunction(current.Value)) { ParseFunction(tokens); } else if (current.TokenType == TokenType.Numeric) { ParseNumber(tokens); } else { throw new ParserExceptionWithPosistion(string.Format("Unrecognised factor at {0}.", current.Position), current.Position); } }
private void ByAttribute() { TokenQueue cq = new TokenQueue(tq.ChompBalanced('[', ']')); // content queue string key = cq.ConsumeToAny("=", "!=", "^=", "$=", "*=", "~="); // eq, not, start, end, contain, match, (no val) if (key.Length == 0) { throw Failure.EmptyString("key"); } cq.ConsumeWhitespace(); if (cq.IsEmpty) { if (key.StartsWith("^", StringComparison.Ordinal)) { evals.Add(new Evaluator.AttributeStarting(key.Substring(1))); } else { evals.Add(new Evaluator.Attribute(key)); } } else { if (cq.MatchChomp("=")) { evals.Add(new Evaluator.AttributeWithValue(key, cq.Remainder())); } else if (cq.MatchChomp("!=")) { evals.Add(new Evaluator.AttributeWithValueNot(key, cq.Remainder())); } else if (cq.MatchChomp("^=")) { evals.Add(new Evaluator.AttributeWithValueStarting(key, cq.Remainder())); } else if (cq.MatchChomp("$=")) { evals.Add(new Evaluator.AttributeWithValueEnding(key, cq.Remainder())); } else if (cq.MatchChomp("*=")) { evals.Add(new Evaluator.AttributeWithValueContaining(key, cq.Remainder())); } else if (cq.MatchChomp("~=")) { evals.Add(new Evaluator.AttributeWithValueMatching(key, new Regex(cq.Remainder()))); } else { throw DomFailure.CannotParseAttributeQuery(query, cq.Remainder()); } } }
/// <summary> /// TermTail := nil | '*' Factor | '/' Factor /// </summary> void ParseTermTail(TokenQueue tokens) { Token current = tokens.PeekToken(); if (current.TokenType == TokenType.Divide) { current = tokens.NextToken(); ParseFactor(tokens); // Append operators postfix EmitBinaryOperator("/", current.Position); ParseTermTail(tokens); } else if (current.TokenType == TokenType.Multiply) { current = tokens.NextToken(); ParseFactor(tokens); // Append operators postfix EmitBinaryOperator("*", current.Position); ParseTermTail(tokens); } else { // nil - but this is ok } }
public override MatchResult?MatchStep(MatchStack stack, MatchFrame frame, TokenQueue q) { int idx = (int)q.Take().Type; var match = idx >= 0 && idx < _bitmap.Length && _bitmap[idx]; return(match ? MatchResult.Matched : MatchResult.NoMatch); }
public override ExcutableCommand Create(TokenQueue seq, Token first, CompilerApplication context) { List <ExcutableCommand> result = context.context.Results; int i; for (i = result.Count - 1; i >= 0; i--) { if (result[i].keyword.Type == TokenType.MACRO_COMMAND) { break; } } ExcutableCommand[] param = new ExcutableCommand[result.Count - i - 1]; for (int j = param.Length - 1, k = result.Count - 1; j >= 0; j--, k--) { param[j] = result[k]; result.RemoveAt(k); } MacroCommand macro = (MacroCommand)result[i]; macro.content = param; result.RemoveAt(i); macro.CompileMacro(); return(null); }
/// <summary> /// ExprTail := nil | '+' Term ExprTail | '-' Term ExprTail /// </summary> void ParseExprTail(TokenQueue tokens) { Token current = tokens.PeekToken(); if (current.TokenType == TokenType.Plus) { current = tokens.NextToken(); ParseTerm(tokens); // Append operators postfix EmitBinaryOperator("+", current.Position); ParseExprTail(tokens); } else if (current.TokenType == TokenType.Minus) { current = tokens.NextToken(); ParseTerm(tokens); // Append operators postfix EmitBinaryOperator("-", current.Position); ParseExprTail(tokens); } else { // nil - but this is ok. } }
/// Function := Name '(' ArgList ')' void ParseFunction(TokenQueue tokens) { var funcStartPosition = tokens.PeekToken().Position; RegisteredFunction function = ParseFunctionName(tokens); Token current = tokens.PeekToken(); if (current.TokenType != TokenType.OpenParenthesis) { throw new ParserExceptionWithPosistion(string.Format("Expected open bracket at {0}.", current.Position), current.Position); } tokens.NextToken(); int args = 0; ParseArgList(tokens, ref args); current = tokens.PeekToken(); if (args != function.ArgCount) { throw new ParserExceptionWithPosistion(string.Format("Invalid number of function parameters in function {0}. Expected {1} at {2}.", function.Name, function.ArgCount, current.Position), current.Position); } if (current.TokenType != TokenType.CloseParenthesis) { throw new ParserExceptionWithPosistion(string.Format("Expected close bracket at {0}.", current.Position), current.Position); } // Append function names after all their arguments. EmitFunction(function, funcStartPosition); tokens.NextToken(); }
public void addFirst() { TokenQueue tq = new TokenQueue("One Two"); tq.ConsumeWord(); tq.AddFirst("Three"); Assert.AreEqual("Three Two", tq.Remainder()); }
/// <summary> /// Parse the supplied expression. /// If the expression is not valid, then a ParserException will be thrown. /// Finally we test to see that all tokens have been parsed. /// If not, this is likely to be an error in the expression, for example something like /// 4535+54345+5345345POWER(2, 3) /// </summary> public void ParseExpression(TokenQueue tokens) { ParseExpressionR(tokens); if (tokens.PeekToken().TokenType != TokenType.EOF) { throw new ParserException(string.Format("Tokens remain after parsing: {0}.", tokens.ToString())); } return; }
public void chompBalancedMatchesAsMuchAsPossible() { TokenQueue tq = new TokenQueue("unbalanced(something(or another"); tq.ConsumeTo("("); string match = tq.ChompBalanced('(', ')'); Assert.AreEqual("something(or another", match); }
public override ExcutableCommand Create(TokenQueue seq, Token first, CompilerApplication context) { context.SetLabel(first.Text, first); LableCommand c = new LableCommand { keyword = first }; return(c); }
private Ast.Stmt ParseContinueStmt(TokenQueue q) { var stmt = new Ast.ContinueStmt { SourceToken = q.SourceToken }; q.Take("continue"); ConsumeSemicolon(q); return(stmt); }
private Ast.Stmt ParseBreakStmt(TokenQueue q) { var stmt = new Ast.BreakStmt { SourceToken = q.SourceToken }; q.Take("break"); ConsumeSemicolon(q); return(stmt); }
private void ParseAssignmentStmtCore(TokenQueue q, Ast.AssignmentStmt stmt) { stmt.VariableName = ParseVariableName(q); if (q.Peek() == "=") { q.Take(); stmt.InitialValue = ParseExpr(q); } ConsumeSemicolon(q); }
/// ArgList :=nil | NonEmptyArgList void ParseArgList(TokenQueue tokens, ref int argc) { Token current = tokens.PeekToken(); // If it is a close parenthesis then its the end of the arglist. if (current.TokenType != TokenType.CloseParenthesis) { ParseNonEmptyArgList(tokens, ref argc); } }
private Ast.Stmt ParseSetStmt(TokenQueue q) { var stmt = new Ast.SetStmt { SourceToken = q.SourceToken }; q.Take("set"); ParseAssignmentStmtCore(q, stmt); return(stmt); }
private void ByAttribute() { TokenQueue cq = new TokenQueue(_tq.ChompBalanced('[', ']')); // content queue string key = cq.ConsumeToAny("=", "!=", "^=", "$=", "*=", "~="); // eq, not, start, end, contain, match, (no val) if (string.IsNullOrEmpty(key)) { throw new Exception("key is empty."); } cq.ConsumeWhitespace(); if (cq.IsEmpty) { if (key.StartsWith("^")) { _evals.Add(new Evaluator.AttributeStarting(key.Substring(1))); } else { _evals.Add(new Evaluator.Attribute(key)); } } else { if (cq.MatchChomp("=")) { _evals.Add(new Evaluator.AttributeWithValue(key, cq.Remainder())); } else if (cq.MatchChomp("!=")) { _evals.Add(new Evaluator.AttributeWithValueNot(key, cq.Remainder())); } else if (cq.MatchChomp("^=")) { _evals.Add(new Evaluator.AttributeWithValueStarting(key, cq.Remainder())); } else if (cq.MatchChomp("$=")) { _evals.Add(new Evaluator.AttributeWithValueEnding(key, cq.Remainder())); } else if (cq.MatchChomp("*=")) { _evals.Add(new Evaluator.AttributeWithValueContaining(key, cq.Remainder())); } else if (cq.MatchChomp("~=")) { _evals.Add(new Evaluator.AttributeWithValueMatching(key, new Regex(cq.Remainder()))); } else { throw new Selector.SelectorParseException("Could not parse attribute query '{0}': unexpected token at '{1}'", _query, cq.Remainder()); } } }
/// <summary> /// Loads a RDF Dataset from the NQuads input using a RDF Handler /// </summary> /// <param name="handler">RDF Handler to use</param> /// <param name="input">Input to load from</param> public void Load(IRdfHandler handler, TextReader input) { if (handler == null) { throw new RdfParseException("Cannot parse an RDF Dataset using a null handler"); } if (input == null) { throw new RdfParseException("Cannot parse an RDF Dataset from a null input"); } try { //Setup Token Queue and Tokeniser NTriplesTokeniser tokeniser = new NTriplesTokeniser(input); tokeniser.NQuadsMode = true; ITokenQueue tokens; switch (this._queueMode) { case TokenQueueMode.AsynchronousBufferDuringParsing: tokens = new AsynchronousBufferedTokenQueue(tokeniser); break; case TokenQueueMode.QueueAllBeforeParsing: tokens = new TokenQueue(tokeniser); break; case TokenQueueMode.SynchronousBufferDuringParsing: default: tokens = new BufferedTokenQueue(tokeniser); break; } tokens.Tracing = this._tracetokeniser; tokens.InitialiseBuffer(); //Invoke the Parser this.Parse(handler, tokens); } catch { throw; } finally { try { input.Close(); } catch { //No catch actions - just cleaning up } } }
private Ast.Stmt ParsePrintStmt(TokenQueue q) { var stmt = new Ast.PrintStmt { SourceToken = q.SourceToken }; q.Take("print"); stmt.Value = ParseExpr(q); ConsumeSemicolon(q); return(stmt); }
public void chompBalanced() { TokenQueue tq = new TokenQueue(":contains(one (two) three) four"); string pre = tq.ConsumeTo("("); string guts = tq.ChompBalanced('(', ')'); string remainder = tq.Remainder(); Assert.AreEqual(":contains", pre); Assert.AreEqual("one (two) three", guts); Assert.AreEqual(" four", remainder); }
public void chompToIgnoreCase() { string t = "<textarea>one < two </TEXTarea>"; TokenQueue tq = new TokenQueue(t); string data = tq.ChompToIgnoreCase("</textarea"); Assert.AreEqual("<textarea>one < two ", data); tq = new TokenQueue("<textarea> one two < three </oops>"); data = tq.ChompToIgnoreCase("</textarea"); Assert.AreEqual("<textarea> one two < three </oops>", data); }
public void ProcessResponseHeaders(WebHeaderCollection resHeaders) { foreach (string name in resHeaders.AllKeys) { if (string.IsNullOrWhiteSpace(name)) { continue; // http/1.1 line } var value = resHeaders[name]; //.Split(';'); if (name.Equals("Set-Cookie", StringComparison.OrdinalIgnoreCase)) { var values = resHeaders["Set-Cookie"].Split(';', ','); foreach (string v in values) { if (string.IsNullOrWhiteSpace(v)) { continue; } var cd = new TokenQueue(v); var cookieName = cd.ChompTo("=").Trim(); var cookieVal = cd.ConsumeTo(";").Trim(); if (cookieVal == null) { cookieVal = string.Empty; } // ignores path, date, domain, secure et al. req'd? if (StringUtil.In(cookieName.ToLowerInvariant(), "domain", "path", "expires", "max-age", "secure", "httponly")) { // This is added for NSoup, since we do headers a bit differently around here. continue; } // name not blank, value not null if (!string.IsNullOrEmpty(cookieName)) { Cookie(cookieName, cookieVal); } } } else { if (!string.IsNullOrEmpty(value)) { Header(name, /*values[0]*/ value); } } } }
public override bool Match(Token first, CompilerApplication context) { TokenQueue tokens = context.context.Tokens; if (tokens.Peek().Text.Equals(":")) { tokens.Peek().Type = TokenType.LABEL; return(true); } return(false); }
private Ast.Stmt ParseWhileStmt(TokenQueue q) { var stmt = new Ast.WhileStmt { SourceToken = q.SourceToken }; q.Take("while"); stmt.Condition = ParseExpr(q); stmt.Block = ParseBlock(q); ConsumeSemicolon(q); return(stmt); }
public void ProcessResponseHeaders(WebHeaderCollection resHeaders) { foreach (string name in resHeaders.Keys) { if (name == null) { continue; // http/1.1 line } string value = resHeaders[name]; //.Split(';'); if (name.Equals("Set-Cookie", StringComparison.InvariantCultureIgnoreCase)) { string[] values = resHeaders["Set-Cookie"].Split(';', ','); foreach (string v in values) { if (v == null) { continue; } TokenQueue cd = new TokenQueue(v); string cookieName = cd.ChompTo("=").Trim(); string cookieVal = cd.ConsumeTo(";").Trim(); if (cookieVal == null) { cookieVal = string.Empty; } // ignores path, date, domain, secure et al. req'd? if (StringUtil.In(cookieName.ToLowerInvariant(), "domain", "path", "expires", "max-age", "secure", "httponly")) { // This is added for Texxtoor.BaseLibrary.Core.HtmlAgility.ToXml, since we do headers a bit differently around here. continue; } // name not blank, value not null if (!string.IsNullOrEmpty(cookieName)) { Cookie(cookieName, cookieVal); } } } else { // only take the first instance of each header if (/*values.Length > 0*/ !string.IsNullOrEmpty(value)) { Header(name, /*values[0]*/ value); } } } }
public override MatchResult?MatchStep(MatchStack stack, MatchFrame frame, TokenQueue q) { switch (q.Take().Type) { case TokenType.Id: case TokenType.Ties: case TokenType.Variable when AllowVariable: return(MatchResult.Matched); default: return(MatchResult.NoMatch); } }
public override ExcutableCommand Create(TokenQueue seq, Token first, CompilerApplication context) { if (base.Match(first, context)) { MacroCommand c = (MacroCommand)Clone(); c.keyword = seq.Dequeue(); c.keyword.Type = TokenType.MACRO_COMMAND; c.parameters = seq.DeQueueLine(); context.SetMacro(c.keyword.Text, c); return(c); } return((MacroCommand)Clone(seq, context.GetMacro(first.Text))); }
private void ByAttribute() { TokenQueue cq = new TokenQueue(tq.ChompBalanced('[', ']')); // content queue string key = cq.ConsumeToAny(AttributeEvals); // eq, not, start, end, contain, match, (no val) Validate.NotEmpty(key); cq.ConsumeWhitespace(); if (cq.IsEmpty()) { if (key.StartsWith("^", StringComparison.Ordinal)) { evals.Add(new Evaluator.AttributeStarting(key.Substring(1))); /*substring*/ } else { evals.Add(new Evaluator.Attribute(key)); } } else { if (cq.MatchChomp("=")) { evals.Add(new Evaluator.AttributeWithValue(key, cq.Remainder())); } else if (cq.MatchChomp("!=")) { evals.Add(new Evaluator.AttributeWithValueNot(key, cq.Remainder())); } else if (cq.MatchChomp("^=")) { evals.Add(new Evaluator.AttributeWithValueStarting(key, cq.Remainder())); } else if (cq.MatchChomp("$=")) { evals.Add(new Evaluator.AttributeWithValueEnding(key, cq.Remainder())); } else if (cq.MatchChomp("*=")) { evals.Add(new Evaluator.AttributeWithValueContaining(key, cq.Remainder())); } else if (cq.MatchChomp("~=")) { evals.Add(new Evaluator.AttributeWithValueMatching(key, new Regex(cq.Remainder(), RegexOptions.Compiled))); } else { throw new Selector.SelectorParseException("Could not parse attribute query '{0}': unexpected token at '{1}'", query, cq.Remainder()); } } }
private Ast.Stmt ParseReturnStmt(TokenQueue q) { var stmt = new Ast.ReturnStmt { SourceToken = q.SourceToken }; q.Take("return"); if (PeekExpr(q)) { stmt.Value = ParseExpr(q); } ConsumeSemicolon(q); return(stmt); }
private Ast.Stmt ParseExecuteStmt(TokenQueue q) { var stmt = new Ast.ExecuteStmt { SourceToken = q.SourceToken }; q.Take("exec", "execute"); if (q.Peek(1) == "=") { stmt.ReturnVariableName = ParseVariableName(q); q.Take("="); } if (q.PeekToken().Type == TokenType.String || q.PeekToken().Type == TokenType.Id) { stmt.ScriptName = q.Take().GetUnescapedText(); } else { throw new SyntaxException(new[] { "string", "identifier" }, q); } if (IsVariableName(q.PeekToken()?.GetUnescapedText() ?? "") && q.Peek(1) == "=") { while (true) { var arg = new Ast.ArgumentPair(); arg.Name = ParseVariableName(q); q.Take("="); if (q.Peek() == "default") { q.Take(); } else { arg.Value = ParseExpr(q); } stmt.Arguments.Add(arg); if (!q.TakeMaybe(",")) { break; } } } ConsumeSemicolon(q); return(stmt); }
/// <summary> /// Parse stream and return the expression tree /// </summary> /// <param name="r">Stream</param> /// <returns>Parsed expression or null if no expression is found on stream</returns> public IOperation Parse(ParsingReader r) { List<IOperation> data = new List<IOperation>(); while (!r.IsEOF) { TokenQueue tokenQueue = new TokenQueue(this, r); var ex = parseSingleStatement(tokenQueue,-1); if (ex == null) break; if (data.Count > 0) data.Add(new Operations.OperationPop()); data.Add(ex); r.SkipWhiteSpaceAndComments(); if (r.Peek() != ';') break; do { r.Read(); r.SkipWhiteSpaceAndComments(); } while (r.Peek() == ';'); } if (data.Count == 0) return null; if (data.Count == 1) return data[0]; return new Operations.OperationExpression(data.ToArray()); }
private static IOperation parseSingleStatement(TokenQueue tokenQueue, int precedenceAtLeast) { Queue<IOperation> queue = new Queue<IOperation>(); Stack<QToken> stack = new Stack<QToken>(); QToken token = null; bool argumentExpected = false; bool dotIsProperty = false; bool exitLoop = false; while (!exitLoop) { token = tokenQueue.Pop(); if (token == null) break; switch (token.TokenType) { case QType.ParenthesisOpen: // C# has typecasts, such as ((IInterface)x) so when seeing an opening (, we must try to read type. // This however does not work if there is an identifier before the (, for example func(Enum.Value,(Enum.Value)). if (stack.Count == 0 || (stack.Peek().TokenType != QType.Id && !stack.Peek().IsOperator(Operators.New))) { string sType = tokenQueue.GetTypeNameFollowedByClosingParenthesis(); if (sType != null) { var q = tokenQueue.Peek(); if (q==null || (q.TokenType!=QType.Id && q.TokenType!=QType.Value && q.TokenType!=QType.Subexpr && !q.IsOpenBrace)) { token = new QToken(QType.Id, sType); goto case QType.Id; } stack.Push(new QToken(Operators.TypeCast) {Param = sType}); argumentExpected = dotIsProperty = false; break; } } goto case QType.SquareOpen; case QType.SquareOpen: case QType.BlockOpen: token.ExtraInt = -(queue.Count + stack.Count + 1); stack.Push(token); argumentExpected = false; dotIsProperty = false; break; case QType.Value: queue.Enqueue(operationFromToken(token)); argumentExpected = false; dotIsProperty = true; break; case QType.Subexpr: queue.Enqueue(operationFromToken(token)); argumentExpected = false; dotIsProperty = true; break; case QType.Typeof: if (tokenQueue.Peek() == null || tokenQueue.Peek().TokenType != QType.ParenthesisOpen) tokenQueue.ThrowParsingException("Expected ("); tokenQueue.Pop(); token.Param = tokenQueue.ReadTypeName(); if (tokenQueue.Peek() == null || tokenQueue.Peek().TokenType != QType.ParenthesisClose) tokenQueue.ThrowParsingException("Expected )"); tokenQueue.Pop(); queue.Enqueue(operationFromToken(token)); argumentExpected = false; dotIsProperty = true; break; case QType.Id: string curId = (string)token.Param; bool startsWithDot = curId.StartsWith(".", StringComparison.Ordinal); if (dotIsProperty) { if (!startsWithDot) tokenQueue.ThrowParsingException("Expected ."); token.Param = curId.Substring(1); token.ExtraInt = 1; } else if (token.ExtraInt == 0) { var n = tokenQueue.Peek(); if (n != null && (n.TokenType != QType.ParenthesisOpen) && (n.TokenType != QType.SquareOpen)) goto case QType.Value; } stack.Push(token); argumentExpected = false; dotIsProperty = true; break; case QType.Colon: tokenQueue.Push(token); exitLoop = true; break; case QType.Operator: Operators op = token.Operator; if (argumentExpected || !dotIsProperty) { if (op == Operators.Minus) token = new QToken(op = Operators.UnaryMinus); if (op == Operators.Plus) token = new QToken(op = Operators.UnaryPlus); } cleanStack(queue, stack, op); if (precedenceAtLeast >= 0 && s_precedence[op] < precedenceAtLeast && stack.Count == 0) { tokenQueue.Push(token); exitLoop = true; argumentExpected = false; break; } switch (op) { case Operators.Or: case Operators.And: { // Or and AND short-circuit, so a || b || c => a?true:(b?true:c) // and a && b &&c => a?(b?c:false):false Stack<IOperation> terms = new Stack<IOperation>(); bool isOr = (op == Operators.Or); do { var e1 = parseSingleStatement(tokenQueue, s_precedence[op] + 1); if (e1 == null) tokenQueue.ThrowParsingException("Expression expected after " + (isOr ? "||" : "&&")); terms.Push(e1); var n = tokenQueue.Peek(); if (n == null || !n.IsOperator(op)) break; tokenQueue.Pop(); } while (true); IOperation o = null; while (terms.Count > 0) { if (o == null) o = terms.Pop(); else o = new Operations.OperationExpression(terms.Pop(), (isOr) ? new Operations.OperationConditional(createConstant(true), o) : new Operations.OperationConditional(o, createConstant(false))); } o = (isOr) ? new Operations.OperationConditional(createConstant(true), o) : new Operations.OperationConditional(o, createConstant(false)); queue.Enqueue(o); argumentExpected = dotIsProperty = false; break; } case Operators.Conditional: { var e1 = parseSingleStatement(tokenQueue, -1); if (e1 == null) tokenQueue.ThrowParsingException("Failed to parse the first part of the conditional expression"); var n = tokenQueue.Pop(); if (n == null || n.TokenType != QType.Colon) tokenQueue.ThrowParsingException("Expected :"); var e2 = parseSingleStatement(tokenQueue, -1); if (e2 == null) tokenQueue.ThrowParsingException("Failed to parse the second part of the conditional expression"); queue.Enqueue(new Operations.OperationConditional(e1, e2)); argumentExpected = dotIsProperty = false; } break; case Operators.Coalesce: { var e2 = parseSingleStatement(tokenQueue, -1); if (e2 == null) tokenQueue.ThrowParsingException("Expression expected after ??"); queue.Enqueue(new Operations.OperationCoalesce(e2)); argumentExpected = dotIsProperty = false; } break; case Operators.Comma: while (stack.Count > 0 && !stack.Peek().IsOpenBrace) queue.Enqueue(operationFromToken(stack.Pop())); if (stack.Count > 0 && stack.Peek().IsOpenBrace) { var p = stack.Pop(); if (p.ExtraInt <= 0) p.ExtraInt = 1; p.ExtraInt++; // Count the number of comma-separated entities in braces stack.Push(p); } argumentExpected = dotIsProperty = false; break; case Operators.New: case Operators.Is: case Operators.As: // After this there is a typename, which in case of typeof() MUST be in parentheses (unlike C++) token.Param = tokenQueue.ReadTypeName(); if (token.Param==null && op!=Operators.New) tokenQueue.ThrowParsingException("Expected type"); stack.Push(token); argumentExpected = false; dotIsProperty = true; break; default: argumentExpected = true; dotIsProperty = false; stack.Push(token); break; } break; case QType.ParenthesisClose: case QType.BlockClose: case QType.SquareClose: if (argumentExpected) tokenQueue.ThrowParsingException("Argument expected"); QType match = QType.ParenthesisOpen; if (token.TokenType == QType.SquareClose) match = QType.SquareOpen; if (token.TokenType == QType.BlockClose) match = QType.BlockOpen; while (stack.Count > 0 && stack.Peek().TokenType != match) { var sp = stack.Pop(); if (sp.IsOpenBrace) tokenQueue.ThrowParsingException("Parentheses or square brackets do not match"); queue.Enqueue(operationFromToken(sp)); } if (stack.Count == 0) { tokenQueue.Push(token); exitLoop = true; break; } var args = stack.Pop().ExtraInt; if (args < 0) args = (args == -(queue.Count + stack.Count + 1)) ? 0 : 1; var nextToken = tokenQueue.Peek(); if (stack.Count > 0 && stack.Peek().IsOperator(Operators.New)) { var newOp = stack.Pop(); switch (token.TokenType) { case QType.SquareClose: if (nextToken == null || nextToken.TokenType != QType.BlockOpen) queue.Enqueue(new Operations.OperationNewObject((string)newOp.Param, args, false)); else { newOp.ExtraInt = args; stack.Push(newOp); } break; case QType.BlockClose: queue.Enqueue(new Operations.OperationCreateBlock(args)); queue.Enqueue(new Operations.OperationNewObject((string)newOp.Param, newOp.ExtraInt + 1, (token.TokenType == QType.BlockClose))); break; default: queue.Enqueue(new Operations.OperationNewObject((string)newOp.Param, args, (token.TokenType == QType.BlockClose))); break; } } else if (token.TokenType == QType.ParenthesisClose || token.TokenType == QType.SquareClose) { if (stack.Count > 0 && (stack.Peek().TokenType == QType.Id)) { var pop = stack.Pop(); string id = (string)pop.Param; bool isProperty = (token.TokenType == QType.SquareClose); queue.Enqueue(new Operations.OperationCall(id, pop.ExtraInt != 0, isProperty, args)); } else if (token.TokenType == QType.SquareClose) queue.Enqueue(new Operations.OperationCall(string.Empty, true, true, args)); } else // if (token.Type == QType.BlockClose) { queue.Enqueue(new Operations.OperationCreateBlock(args)); } argumentExpected = false; dotIsProperty = true; break; } } if (argumentExpected) tokenQueue.ThrowParsingException("Argument expected"); while (stack.Count > 0) queue.Enqueue(operationFromToken(stack.Pop())); IOperation ex; if (queue.Count == 0) return null; if (queue.Count == 1) ex = queue.Peek(); else ex = new Operations.OperationExpression(queue.ToArray()); if (ex.StackBalance != 1) tokenQueue.ThrowParsingException("Invalid expression syntax"); return ex; }
/*Create a token buffer */ public TokenBuffer(TokenStream input_) { input = input_; queue = new TokenQueue(1); }