// Copyright 2008 - 2010 Herre Kuijpers - <herre.kuijpers@gmail.com>
//
// This source file(s) may be redistributed, altered and customized
// by any means PROVIDING the authors name and all copyright
// notices remain intact.
// THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED. USE IT AT YOUR OWN RISK. THE AUTHOR ACCEPTS NO
// LIABILITY FOR ANY DATA DAMAGE/LOSS THAT THIS PRODUCT MAY CAUSE.
//-----------------------------------------------------------------------
// version 0.4
using System;
using System.Collections.Generic;
using System.Text;
namespace TinyPG.Compiler
{
#region ParseTree
public class ParseErrors : List<ParseError>
{
public void AddUnexptectedTokenError(string unexpectedToken, string expectedToken, int start, int end)
{
this.Add(new ParseError("Unexpected token '" + unexpectedToken.Replace("\n", "") + "' found.Expected '" + expectedToken + "'", 0, 0, start, end - start));
}
public List<string> GetAllErrors()
{
List<string> errors = new List<string>();
foreach (ParseError err in this)
{
errors.Add(err.Message);
}
return errors;
}
}
public class ParseError
{
private string message;
private int line;
private int col;
private int pos;
private int length;
public int Line { get { return line; } }
public int Column { get { return col; } }
public int Position { get { return pos; } }
public int Length { get { return length; } }
public string Message { get { return message; } }
public ParseError(string message, int line, int col, int pos, int length)
{
this.message = message;
this.line = line;
this.col = col;
this.pos = pos;
this.length = length;
}
}
// rootlevel of the node tree
public partial class ParseTree : ParseNode
{
public ParseErrors Errors;
public List<Token> Skipped;
public ParseTree() : base(new Token(), "ParseTree")
{
Token.Type = TokenType.Start;
Token.Text = "Root";
Skipped = new List<Token>();
Errors = new ParseErrors();
}
public string PrintTree()
{
StringBuilder sb = new StringBuilder();
int indent = 0;
PrintNode(sb, this, indent);
return sb.ToString();
}
private void PrintNode(StringBuilder sb, ParseNode node, int indent)
{
string space = "".PadLeft(indent, ' ');
sb.Append(space);
sb.AppendLine(node.Text);
foreach (ParseNode n in node.Nodes)
PrintNode(sb, n, indent + 2);
}
/// <summary>
/// this is the entry point for executing and evaluating the parse tree.
/// </summary>
/// <param name="paramlist">additional optional input parameters</param>
/// <returns>the output of the evaluation function</returns>
public object Eval(params object[] paramlist)
{
return Nodes[0].Eval(this, paramlist);
}
}
public partial class ParseNode
{
protected string text;
protected List<ParseNode> nodes;
public List<ParseNode> Nodes {
get {return nodes;}
}
public Token Token; // the token/rule
public string Text { // text to display in parse tree
get { return text;}
set { text = value; }
}
public virtual ParseNode CreateNode(Token token, string text)
{
return new ParseNode(token, text);
}
protected object GetValue(ParseTree tree, TokenType type, int index)
{
return GetValue(tree, type, ref index);
}
protected object GetValue(ParseTree tree, TokenType type, ref int index)
{
object o = null;
if (index < 0) return o;
// left to right
foreach (ParseNode node in nodes)
{
if (node.Token.Type == type)
{
index--;
if (index < 0)
{
o = node.Eval(tree);
break;
}
}
}
return o;
}
protected ParseNode(Token token, string text)
{
this.Token = token;
this.text = text;
this.nodes = new List<ParseNode>();
}
/// <summary>
/// this implements the evaluation functionality, cannot be used directly
/// </summary>
/// <param name="tree">the parsetree itself</param>
/// <param name="paramlist">optional input parameters</param>
/// <returns>a partial result of the evaluation</returns>
internal object Eval(ParseTree tree, params object[] paramlist)
{
object Value = null;
switch (Token.Type)
{
case TokenType.Start:
Value = EvalStart(tree, paramlist);
break;
case TokenType.ExtProduction:
Value = EvalExtProduction(tree, paramlist);
break;
case TokenType.Attribute:
Value = EvalAttribute(tree, paramlist);
break;
case TokenType.Production:
Value = EvalProduction(tree, paramlist);
break;
case TokenType.Rule:
Value = EvalRule(tree, paramlist);
break;
case TokenType.Subrule:
Value = EvalSubrule(tree, paramlist);
break;
case TokenType.Symbol:
Value = EvalSymbol(tree, paramlist);
break;
case TokenType.BinaryOper:
Value = EvalBinaryOper(tree, paramlist);
break;
default:
Value = Token.Text;
break;
}
return Value;
}
protected virtual object EvalStart(ParseTree tree, params object[] paramlist)
{
throw new NotImplementedException();
}
protected virtual object EvalExtProduction(ParseTree tree, params object[] paramlist)
{
throw new NotImplementedException();
}
protected virtual object EvalAttribute(ParseTree tree, params object[] paramlist)
{
throw new NotImplementedException();
}
protected virtual object EvalProduction(ParseTree tree, params object[] paramlist)
{
throw new NotImplementedException();
}
protected virtual object EvalRule(ParseTree tree, params object[] paramlist)
{
throw new NotImplementedException();
}
protected virtual object EvalSubrule(ParseTree tree, params object[] paramlist)
{
throw new NotImplementedException();
}
protected virtual object EvalSymbol(ParseTree tree, params object[] paramlist)
{
throw new NotImplementedException();
}
protected virtual object EvalBinaryOper(ParseTree tree, params object[] paramlist)
{
throw new NotImplementedException();
}
}
#endregion ParseTree
}