freeso/TSOClient/FSO.UI/Framework/Parser/UIScriptParser.cs
2023-11-25 15:55:49 +00:00

314 lines
No EOL
13 KiB
C#

//Generated by the GOLD Parser Builder
namespace FSO.Client.UI.Framework.Parser
{
using System.IO;
using System.Collections.Generic;
using GOLDEngine;
class UIScriptParser
{
private Parser parser = new Parser();
private Dictionary<Token, object> DataMap = new Dictionary<Token, object>();
private enum SymbolIndex
{
@Eof = 0, // (EOF)
@Error = 1, // (Error)
@Comment = 2, // Comment
@Newline = 3, // NewLine
@Whitespace = 4, // Whitespace
@Num = 5, // '#'
@Ltexclamminusminus = 6, // '<!--'
@Minusminusgt = 7, // '-->'
@Divgt = 8, // '/>'
@Lt = 9, // '<'
@Ltdiv = 10, // '</'
@Eq = 11, // '='
@Gt = 12, // '>'
@Beginliteral = 13, // BeginLiteral
@Charname = 14, // CharName
@Charnumber = 15, // CharNumber
@Endliteral = 16, // EndLiteral
@Id = 17, // ID
@Stringliteral = 18, // StringLiteral
@Attribute = 19, // <Attribute>
@Attributes = 20, // <Attributes>
@Content = 21, // <Content>
@Endtag = 22, // <End Tag>
@Object = 23, // <Object>
@Objects = 24, // <Objects>
@Optionalid = 25, // <OptionalID>
@Starttag = 26, // <Start Tag>
@Text = 27, // <Text>
@Unarytag = 28, // <Unary Tag>
@Word = 29 // <Word>
}
private enum ProductionIndex
{
@Objects = 0, // <Objects> ::= <Object> <Objects>
@Objects2 = 1, // <Objects> ::= <Object>
@Object_Beginliteral_Endliteral = 2, // <Object> ::= BeginLiteral <Content> EndLiteral
@Object = 3, // <Object> ::= <Start Tag>
@Object2 = 4, // <Object> ::= <Unary Tag>
@Starttag_Lt_Id_Gt = 5, // <Start Tag> ::= '<' ID <OptionalID> <Attributes> '>'
@Endtag_Ltdiv_Id_Gt = 6, // <End Tag> ::= '</' ID '>'
@Unarytag_Lt_Id_Divgt = 7, // <Unary Tag> ::= '<' ID <OptionalID> <Attributes> '/>'
@Optionalid_Stringliteral = 8, // <OptionalID> ::= StringLiteral
@Optionalid = 9, // <OptionalID> ::=
@Content = 10, // <Content> ::= <Objects>
@Content2 = 11, // <Content> ::= <Text>
@Attributes = 12, // <Attributes> ::= <Attribute> <Attributes>
@Attributes2 = 13, // <Attributes> ::=
@Attribute_Id_Eq_Stringliteral = 14, // <Attribute> ::= ID '=' StringLiteral
@Attribute_Id_Eq_Id = 15, // <Attribute> ::= ID '=' ID
@Text = 16, // <Text> ::= <Text> <Word>
@Text2 = 17, // <Text> ::= <Word>
@Word_Id = 18, // <Word> ::= ID
@Word_Eq = 19, // <Word> ::= '='
@Word_Charname = 20, // <Word> ::= CharName
@Word_Charnumber = 21 // <Word> ::= CharNumber
}
public object program; //You might derive a specific object
public void Setup()
{
//This procedure can be called to load the parse tables. The class can
//read tables using a BinaryReader.
parser.LoadTables(new BinaryReader(new FileStream("Content/UIScript.egt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite)));
}
public bool Parse(TextReader reader)
{
//This procedure starts the GOLD Parser Engine and handles each of the
//messages it returns. Each time a reduction is made, you can create new
//custom object and reassign the .CurrentReduction property. Otherwise,
//the system will use the Reduction object that was returned.
//
//The resulting tree will be a pure representation of the language
//and will be ready to implement.
GOLDEngine.ParseMessage response;
bool done; //Controls when we leave the loop
bool accepted = false; //Was the parse successful?
parser.Open(reader);
parser.TrimReductions = false; //Please read about this feature before enabling
done = false;
while (!done)
{
response = parser.Parse();
switch (response)
{
case GOLDEngine.ParseMessage.LexicalError:
//Cannot recognize token
done = true;
break;
case GOLDEngine.ParseMessage.SyntaxError:
//Expecting a different token
done = true;
break;
case GOLDEngine.ParseMessage.Reduction:
//Create a customized object to store the reduction
CreateNewObject(parser.CurrentReduction as GOLDEngine.Reduction);
break;
case GOLDEngine.ParseMessage.Accept:
//Accepted!
//program = parser.CurrentReduction //The root node!
done = true;
accepted = true;
break;
case GOLDEngine.ParseMessage.TokenRead:
//You don't have to do anything here.
break;
case GOLDEngine.ParseMessage.InternalError:
//INTERNAL ERROR! Something is horribly wrong.
done = true;
break;
case GOLDEngine.ParseMessage.NotLoadedError:
//This error occurs if the CGT was not loaded.
done = true;
break;
case GOLDEngine.ParseMessage.GroupError:
//GROUP ERROR! Unexpected end of file
done = true;
break;
}
} //while
return accepted;
}
private object CreateNewObject(GOLDEngine.Reduction r)
{
object result = r.ToText();
for (int i = 0; i < r.Count; i++)
{
if (!DataMap.ContainsKey(r[i]))
{
DataMap[r[i]] = r[i].ToText();
}
}
switch ((ProductionIndex)r.Production.TableIndex())
{
case ProductionIndex.Objects:
var newResult = new List<UINode>();
newResult.Add((UINode)DataMap[r[0]]);
newResult.AddRange((List<UINode>)DataMap[r[1]]);
result = newResult;
program = result;
// <Objects> ::= <Object> <Objects>
break;
case ProductionIndex.Objects2:
// <Objects> ::= <Object>
var newResult2 = new List<UINode>();
newResult2.Add((UINode)DataMap[r[0]]);
result = newResult2;
program = result;
break;
case ProductionIndex.Object_Beginliteral_Endliteral:
// <Object> ::= BeginLiteral <Content> EndLiteral
result = UIGroup.FromReduction(r, DataMap);
break;
case ProductionIndex.Object:
// <Object> ::= <Start Tag>
result = DataMap[r[0]];
break;
case ProductionIndex.Object2:
// <Object> ::= <Unary Tag>
break;
case ProductionIndex.Starttag_Lt_Id_Gt:
// <Start Tag> ::= '<' ID <OptionalID> <Attributes> '>'
var node = new UINode();
node.Name = (string)DataMap[r[1]];
node.ID = (string)DataMap[r[2]];
var atts = (List<KeyValuePair<string, string>>)DataMap[r[3]];
foreach (var att in atts)
{
node[att.Key] = att.Value;
}
result = node;
break;
case ProductionIndex.Endtag_Ltdiv_Id_Gt:
// <End Tag> ::= '</' ID '>'
break;
case ProductionIndex.Unarytag_Lt_Id_Divgt:
// <Unary Tag> ::= '<' ID <OptionalID> <Attributes> '/>'
break;
case ProductionIndex.Optionalid_Stringliteral:
// <OptionalID> ::= StringLiteral
result = GetStringLiteral((string)DataMap[r[0]]);
break;
case ProductionIndex.Optionalid:
// <OptionalID> ::=
result = null;
break;
case ProductionIndex.Content:
// <Content> ::= <Objects>
var newResult3 = new List<UINode>();
newResult3.AddRange((List<UINode>)DataMap[r[0]]);
result = newResult3;
break;
case ProductionIndex.Content2:
// <Content> ::= <Text>
var newResult4 = new List<UINode>();
newResult4.Add((UINode)DataMap[r[0]]);
result = newResult4;
break;
case ProductionIndex.Attributes:
// <Attributes> ::= <Attribute> <Attributes>
var attributeList = new List<KeyValuePair<string, string>>();
attributeList.Add((KeyValuePair<string, string>)DataMap[r[0]]);
if (r.Count > 1)
{
attributeList.AddRange((List<KeyValuePair<string, string>>)DataMap[r[1]]);
}
result = attributeList;
break;
case ProductionIndex.Attributes2:
// <Attributes> ::=
result = new List<KeyValuePair<string, string>>();
break;
case ProductionIndex.Attribute_Id_Eq_Stringliteral:
// <Attribute> ::= ID '=' StringLiteral
result = new KeyValuePair<string, string>((string)DataMap[r[0]], GetStringLiteral((string)DataMap[r[2]]));
break;
case ProductionIndex.Attribute_Id_Eq_Id:
// <Attribute> ::= ID '=' ID
result = new KeyValuePair<string, string>((string)DataMap[r[0]], (string)DataMap[r[2]]);
break;
case ProductionIndex.Text:
// <Text> ::= <Text> <Word>
break;
case ProductionIndex.Text2:
// <Text> ::= <Word>
break;
case ProductionIndex.Word_Id:
// <Word> ::= ID
break;
case ProductionIndex.Word_Eq:
// <Word> ::= '='
break;
case ProductionIndex.Word_Charname:
// <Word> ::= CharName
break;
case ProductionIndex.Word_Charnumber:
// <Word> ::= CharNumber
break;
} //switch
DataMap[r] = result;
return result;
}
private string GetStringLiteral(string input)
{
if (input.StartsWith("\""))
{
input = input.Substring(1);
}
if (input.EndsWith("\""))
{
input = input.Substring(0, input.Length - 1);
}
return input;
}
}; //MyParser
}