예제 #1
0
    private AstNode CreateNode(ActionRecord reduceAction, SourceSpan sourceSpan, AstNodeList childNodes)
    {
      NonTerminal nonTeminal = reduceAction.NonTerminal;
      AstNode result;
      AstNodeArgs args = new AstNodeArgs(nonTeminal, sourceSpan, childNodes);

      Type defaultNodeType = _context.Compiler.Data.DefaultNodeType;
      Type ntNodeType = nonTeminal.NodeType ?? defaultNodeType ?? typeof(AstNode);

      bool isList = nonTeminal.IsSet(TermOptions.IsList);
      if (isList && childNodes.Count > 1 && childNodes[0].Term == nonTeminal)
      {
        result = childNodes[0];
        AstNode newChild = childNodes[childNodes.Count - 1];
        newChild.Parent = result;
        result.ChildNodes.Add(newChild);
        return result;
      }

      if (nonTeminal.IsSet(TermOptions.IsStarList) && childNodes.Count == 1)
      {
        childNodes = childNodes[0].ChildNodes;
      }

      if (!isList && !nonTeminal.IsSet(TermOptions.IsPunctuation) && childNodes.Count == 1)
      {
        Type childNodeType = childNodes[0].Term.NodeType ?? defaultNodeType ?? typeof(AstNode);
        if (childNodeType == ntNodeType || childNodeType.IsSubclassOf(ntNodeType))
          return childNodes[0];
      }

      result = null;
      if (ntNodeType == typeof(AstNode))
      {
        result = new AstNode(args);
      }
      else
      {
        ConstructorInfo ctor = ntNodeType.GetConstructor(new Type[] { typeof(AstNodeArgs) });
        if (ctor == null)
          throw new Exception("Failed to located constructor: " + ntNodeType.ToString() + "(AstNodeArgs args)");

        result = (AstNode)ctor.Invoke(new object[] { args });
      }

      return result;
    }
예제 #2
0
    private void ExecuteReduceAction(ActionRecord action)
    {
      ParserState oldState = _currentState;
      int popCnt = action.PopCount;

      AstNodeList childNodes = new AstNodeList();
      for (int i = 0; i < action.PopCount; i++)
      {
        AstNode child = _stack[_stack.Count - popCnt + i].Node;
        if (!child.Term.IsSet(TermOptions.IsPunctuation))
          childNodes.Add(child);
      }

      SourceSpan newNodeSpan;
      if (popCnt == 0)
      {
        newNodeSpan = new SourceSpan(_currentToken.Location, 0);
      }
      else
      {
        SourceLocation firstPopLoc = _stack[_stack.Count - popCnt].Node.Location;
        int lastPopEndPos = _stack[_stack.Count - 1].Node.Span.EndPos;
        newNodeSpan = new SourceSpan(firstPopLoc, lastPopEndPos - firstPopLoc.Position);
        _currentState = _stack[_stack.Count - popCnt].State;
        _stack.Pop(popCnt);
      }
      
      AstNode node = CreateNode(action, newNodeSpan, childNodes);
      _stack.Push(node, _currentState);

      ActionRecord gotoAction;
      if (_currentState.Actions.TryGetValue(action.NonTerminal.Key, out gotoAction))
      {
        _currentState = gotoAction.NewState;
      }
      else
        throw new CompilerException(string.Format("Cannot find transition for input {0}; state: {1}, popped state: {2}",
              action.NonTerminal, oldState, _currentState));
    }