mirror of
https://github.com/riperiperi/FreeSO
synced 2026-08-13 20:26:13 -04:00
314 lines
No EOL
13 KiB
C#
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
|
|
} |