/// <summary> /// Create CodeNode representing hierarchy sequence. /// </summary> /// <returns>CodeNode created according to layout.</returns> public CodeNode HierarchyLayout() { var node = new CodeNode(_lexer.Move(), NodeTypes.hierarchy); if (_checkToken("("))//function call { node.NodeType = NodeTypes.call; resolveBracket(() => { node.AddArgument(_nextTree()); return(false); }, "(", ",", ")", "Error in call, expected '{0}'"); //on fail throw exception node.EndingToken = _lexer.Current.Previous; //aby ukazoval na zavorku } if (_shiftToken(".")) { var child = HierarchyLayout(); if (child == null) { throw CSharpSyntax.ParsingException(_lexer.Current, "Expected identifier after '.'"); } node.Child = child; } if (_checkToken("[")) { var indexer = IndexerLayout(); node.SetIndexer(indexer); } if (_checkToken("{")) //initializer { var seq = InitializerLayout(); node.SetSubsequence(seq); } return(node); }
/// <summary> /// repair newNode if prefix/postfix operator, according to expect prefix/postfix context. /// </summary> /// <param name="newNode">The new node.</param> /// <param name="operands">The operands.</param> /// <param name="expectPrefix">if set to <c>true</c> prefix operator is expected.</param> /// <param name="expectPostfix">if set to <c>true</c> postfix operator is expected.</param> private void operatorContext(CodeNode newNode, Stack <CodeNode> operands, bool expectPrefix, bool expectPostfix) { bool shouldRepair = false; NodeTypes nodeType = newNode.NodeType; CodeNode argument = null; if (expectPrefix && _language.IsPrefixOperator(newNode.Value)) { shouldRepair = true; nodeType = NodeTypes.prefixOperator; argument = _getTree(); } else if (expectPostfix && _language.IsPostfixOperator(newNode.Value)) { shouldRepair = true; nodeType = NodeTypes.postOperator; //postfix operator has argument already on the stack argument = operands.Pop(); } if (!shouldRepair) { //nothing to repair return; } newNode.NodeType = nodeType; newNode.AddArgument(argument); newNode.IsTreeEnding |= argument.IsTreeEnding; }
/// <summary> /// Create CodeNode representing conditional block. /// </summary> /// <returns>CodeNode created according to layout.</returns> public CodeNode CondBlockLayout() { var condNode = new CodeNode(_lexer.Move(), NodeTypes.block); condition(condNode); //on { nextTree gives sequence, else return command condNode.AddArgument(_nextTree()); if (_shiftToken("else")) { condNode.AddArgument(_nextTree()); } return(condNode); }
/// <summary> /// Create CodeNode representing for block. /// </summary> /// <returns>CodeNode created according to layout.</returns> public CodeNode ForeachLayout() { var node = new CodeNode(_lexer.Move(), NodeTypes.block); _shiftToken("(", "Error in Foreach layout, expected '('"); var declaration = _nextTree(); node.AddArgument(declaration); _shiftToken("in", "Expected 'in'"); var expression = _nextTree(); node.AddArgument(expression); _shiftToken(")", "Error in For layout, expected ')'"); node.Child = _nextTree(); node.EndingToken = _lexer.Current; return(node); }
/// <summary> /// Create <see cref="CodeNode"/> representing do{}while() block /// </summary> /// <returns><see cref="CodeNode"/> created according to layout</returns> public CodeNode DoLayout() { var commandNode = new CodeNode(_lexer.Move(), NodeTypes.block); //on { nextTree gives sequence, else return command commandNode.AddArgument(_nextTree()); _shiftToken("while", "Missing {0} after do"); condition(commandNode); commandNode.EndingToken = _lexer.Current.Next; return(commandNode); }
/// <summary> /// Create CodeNode representing expression prefixed with opening bracket. /// </summary> /// <returns>CodeNode created according to layout.</returns> public CodeNode BracketLayout() { var node = new CodeNode(_lexer.Move(), NodeTypes.bracket); node.AddArgument(_nextTree()); _shiftToken(")", "Expected closing {0}"); if (_shiftToken(".")) { //call on expression node.Child = HierarchyLayout(); } return(node); }
/// <summary> /// Create CodeNode representing switch block. /// </summary> /// <returns>CodeNode created according to layout.</returns> public CodeNode SwitchLayout() { var switchNode = new CodeNode(_lexer.Move(), NodeTypes.block); condition(switchNode); _shiftToken("{", "expected '{' in switch layout"); var inSwitch = true; while (inSwitch) { var label = _current(); switch (label) { case "case": case "default": var labelBlock = new CodeNode(_lexer.Move(), NodeTypes.block); if (labelBlock.Value == "case") { labelBlock.AddArgument(_nextTree()); } _shiftToken(":", "expected '{0}' after '{1}', in switch statement", label); var lines = new List <CodeNode>(); while (_current() != "case" && _current() != "default" && _current() != "}") { lines.Add(_nextTree()); _shiftToken(";"); } labelBlock.SetSubsequence(lines, _lexer.Current); switchNode.AddArgument(labelBlock); break; case "}": inSwitch = false; break; default: throw CSharpSyntax.ParsingException(_lexer.Current, "unrecognized label '{0}' in switch statement", label); } } _shiftToken("}", "expected '{0}' in switch layout"); return(switchNode); }
/// <summary> /// Satisfy given operator node. Satisfied operator is added into operands stack. /// </summary> /// <param name="operatorNode">Operator to satisfy.</param> /// <param name="operands">Operands used for satisfying.</param> private void satisfyOperator(CodeNode operatorNode, Stack <CodeNode> operands) { var arity = _language.Arity(operatorNode); if (operands.Count < arity) { throw CSharpSyntax.ParsingException(operatorNode, "There aren't enough operands for the operator {0}", operatorNode.Value); } var reverseStack = new Stack <CodeNode>(); for (int i = 0; i < arity; i++) { reverseStack.Push(operands.Pop()); } for (int i = 0; i < arity; i++) { operatorNode.AddArgument(reverseStack.Pop()); } operands.Push(operatorNode); }
/// <summary> /// Create CodeNode representing for block. /// </summary> /// <returns>CodeNode created according to layout.</returns> public CodeNode ForLayout() { var node = new CodeNode(_lexer.Move(), NodeTypes.block); _shiftToken("(", "Error in For layout, expected '('"); for (int i = 0; i < 3; i++) { node.AddArgument(_nextTree()); if (i < 2) { _shiftToken(";", "Error in For layout, expected ';'"); } } _shiftToken(")", "Error in For layout, expected ')'"); node.Child = _nextTree(); node.EndingToken = _lexer.Current; return(node); }
/// <summary> /// Add condition argument to given node. /// </summary> /// <param name="condNode">Node to add condition argument.</param> private void condition(CodeNode condNode) { _shiftToken("(", "expected '{0}' in {1} clause", condNode.Value); condNode.AddArgument(_nextTree()); _shiftToken(")", "expected '{0}' in {1} clause", condNode.Value); }