328 lines
9.0 KiB
C#
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();
|
|
}
|
|
}
|
|
}
|
|
}
|