Files
libremetaverse/LibreMetaverse.LslTools/Tools/Lexer.cs
2024-06-30 16:43:03 -05:00

328 lines
9.0 KiB
C#

/*
* Copyright (c) 2019-2024, Sjofn LLC
* All rights reserved.
*
* - Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* - Neither the name of the openmetaverse.co nor the names
* of its contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.IO;
namespace LibreMetaverse.LslTools
{
public class Lexer
{
internal LineManager m_LineManager = new LineManager();
public string m_state = "YYINITIAL";
public bool m_debug;
public string m_buf;
private YyLexer m_tokens;
public string yytext;
public int m_pch;
private bool m_matching;
private int m_startMatch;
public Lexer(YyLexer tks)
{
this.m_state = "YYINITIAL";
this.tokens = tks;
}
public SourceLineInfo sourceLineInfo(int pos)
{
return new SourceLineInfo(this, pos);
}
public string sourceLine(SourceLineInfo s)
{
return this.m_buf.Substring(s.startOfLine, s.endOfLine - s.startOfLine);
}
public string Saypos(int pos)
{
return this.sourceLineInfo(pos).ToString();
}
public Dfa m_start => (Dfa) this.m_tokens.starts[(object) this.m_state];
public YyLexer tokens
{
get => this.m_tokens;
set
{
this.m_tokens = value;
this.m_tokens.GetDfa();
}
}
public int yypos => this.m_pch;
public void yy_begin(string newstate)
{
this.m_state = newstate;
}
private bool Match(ref TOKEN tok, Dfa dfa)
{
char ch = this.PeekChar();
int pch = this.m_pch;
int mark = 0;
if (this.m_debug)
{
Console.Write("state {0} with ", (object) dfa.m_state);
if (char.IsLetterOrDigit(ch) || char.IsPunctuation(ch))
Console.WriteLine(ch);
else
Console.WriteLine("#" + (object) (int) ch);
}
if (dfa.m_actions != null)
mark = this.Mark();
Dfa dfa1;
if ((dfa1 = (Dfa) dfa.m_map[(object) this.m_tokens.Filter(ch)]) == null)
{
if (this.m_debug)
Console.Write("{0} no arc", (object) dfa.m_state);
if (dfa.m_actions != null)
{
if (this.m_debug)
Console.WriteLine(" terminal");
return this.TryActions(dfa, ref tok);
}
if (this.m_debug)
Console.WriteLine(" fails");
return false;
}
this.Advance();
if (!this.Match(ref tok, dfa1))
{
if (this.m_debug)
Console.WriteLine("back to {0} with {1}", (object) dfa.m_state, (object) ch);
if (dfa.m_actions != null)
{
if (this.m_debug)
Console.WriteLine("{0} succeeds", (object) dfa.m_state);
this.Restore(mark);
return this.TryActions(dfa, ref tok);
}
if (this.m_debug)
Console.WriteLine("{0} fails", (object) dfa.m_state);
return false;
}
if (dfa.m_reswds >= 0)
((ResWds) this.m_tokens.reswds[(object) dfa.m_reswds]).Check(this, ref tok);
if (this.m_debug)
{
Console.Write("{0} matched ", (object) dfa.m_state);
if (this.m_pch <= this.m_buf.Length)
Console.WriteLine(this.m_buf.Substring(pch, this.m_pch - pch));
else
Console.WriteLine(this.m_buf.Substring(pch));
}
return true;
}
public void Start(StreamReader inFile)
{
this.m_state = "YYINITIAL";
this.m_LineManager.lines = 1;
this.m_LineManager.list = (LineList) null;
inFile = new StreamReader(inFile.BaseStream, this.m_tokens.m_encoding);
this.m_buf = inFile.ReadToEnd();
if (this.m_tokens.toupper)
this.m_buf = this.m_buf.ToUpper();
for (this.m_pch = 0; this.m_pch < this.m_buf.Length; ++this.m_pch)
{
if (this.m_buf[this.m_pch] == '\n')
this.m_LineManager.newline(this.m_pch);
}
this.m_pch = 0;
}
public void Start(CsReader inFile)
{
this.m_state = "YYINITIAL";
inFile = new CsReader(inFile, this.m_tokens.m_encoding);
this.m_LineManager = inFile.lm;
if (!inFile.Eof())
{
this.m_buf = inFile.ReadLine();
while (!inFile.Eof())
{
this.m_buf += "\n";
this.m_buf += inFile.ReadLine();
}
}
if (this.m_tokens.toupper)
this.m_buf = this.m_buf.ToUpper();
this.m_pch = 0;
}
public void Start(string buf)
{
this.m_state = "YYINITIAL";
this.m_LineManager.lines = 1;
this.m_LineManager.list = (LineList) null;
this.m_buf = buf + "\n";
for (this.m_pch = 0; this.m_pch < this.m_buf.Length; ++this.m_pch)
{
if (this.m_buf[this.m_pch] == '\n')
this.m_LineManager.newline(this.m_pch);
}
if (this.m_tokens.toupper)
this.m_buf = this.m_buf.ToUpper();
this.m_pch = 0;
}
public TOKEN Next()
{
TOKEN tok = (TOKEN) null;
while (this.PeekChar() != char.MinValue)
{
this.Matching(true);
if (!this.Match(ref tok, (Dfa) this.m_tokens.starts[(object) this.m_state]))
{
if (this.yypos == 0)
Console.Write("Check text encoding.. ");
int num = (int) this.PeekChar();
this.m_tokens.erh.Error((CSToolsException) new CSToolsStopException(2, this, "illegal character <" + (object) (char) num + "> " + (object) num));
return (TOKEN) null;
}
this.Matching(false);
if (tok != null)
{
tok.pos = this.m_pch - this.yytext.Length;
return tok;
}
}
return (TOKEN) null;
}
private bool TryActions(Dfa dfa, ref TOKEN tok)
{
int length = this.m_pch - this.m_startMatch;
if (length == 0)
return false;
this.yytext = this.m_startMatch + length > this.m_buf.Length ? this.m_buf.Substring(this.m_startMatch) : this.m_buf.Substring(this.m_startMatch, length);
Dfa.Action action = dfa.m_actions;
bool reject = true;
while (reject && action != null)
{
int aAct = action.a_act;
reject = false;
action = action.a_next;
if (action == null && dfa.m_tokClass != "")
{
if (this.m_debug)
Console.WriteLine("creating a " + dfa.m_tokClass);
tok = (TOKEN) Tfactory.create(dfa.m_tokClass, this);
}
else
{
tok = this.m_tokens.OldAction(this, ref this.yytext, aAct, ref reject);
if (this.m_debug && !reject)
Console.WriteLine("Old action " + (object) aAct);
}
}
return !reject;
}
public char PeekChar()
{
if (this.m_pch < this.m_buf.Length)
return this.m_buf[this.m_pch];
return this.m_pch == this.m_buf.Length && this.m_tokens.usingEOF ? char.MaxValue : char.MinValue;
}
public void Advance()
{
++this.m_pch;
}
public virtual int GetChar()
{
int num = (int) this.PeekChar();
++this.m_pch;
return num;
}
public void UnGetChar()
{
if (this.m_pch <= 0)
return;
--this.m_pch;
}
private int Mark()
{
return this.m_pch - this.m_startMatch;
}
private void Restore(int mark)
{
this.m_pch = this.m_startMatch + mark;
}
private void Matching(bool b)
{
this.m_matching = b;
if (!b)
return;
this.m_startMatch = this.m_pch;
}
public Lexer._Enumerator GetEnumerator()
{
return new Lexer._Enumerator(this);
}
public void Reset()
{
this.m_pch = 0;
this.m_LineManager.backto(0);
}
public class _Enumerator
{
private Lexer lxr;
public _Enumerator(Lexer x)
{
this.lxr = x;
this.Current = (TOKEN) null;
}
public bool MoveNext()
{
this.Current = this.lxr.Next();
return this.Current != null;
}
public TOKEN Current { get; private set; }
public void Reset()
{
this.lxr.Reset();
}
}
}
}