using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace Compiler
{
class Reader
{
private string str;
private int lookahead;
private StreamReader fs;
private bool readfromfile = false;
private bool eof = false;
public Reader(string input)
{
str = new string(input);
lookahead = 0;
readfromfile = false;
}
public Reader() { }
public void openFile(string path)
{
fs = new StreamReader(path);
readfromfile = true;
eof = false;
}
public char next()
{
if (!readfromfile)
{
try
{
return str[lookahead++];
}
catch (Exception)
{
if (lookahead <= str.Length + 1)
{
return ' ';
}
else
{
throw new Exception("End of File");
}
}
}
else
{
if (fs.Peek() >= 0)
{
return (char)fs.Read();
}
else
{
if (eof) throw new Exception("End of File");
eof = true;
return ' ';
}
}
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
namespace Compiler
{
class Lexer
{
private Reader reader;
private char peek;
public int line;
private Hashtable words;
private void increasePeek() => peek = reader.next();
private void increPeekToUseful()
{
for (; ; increasePeek())
{
if (peek == ' ' || peek == '\t')
{
continue;
}
if (peek == '\n' || peek == '\r')
{
line++;
continue;
}
else break;
}
}
/// <summary>
/// 处理运算符,可能为多元运算符或注释
/// 当处理注释时,返回null,peek为' '
/// 当处理运算符时,返回运算符,peek为下一个词素
/// </summary>
private Token? handleSigns()
{
char pre = peek;
increasePeek();
switch (pre)
{
case '/':
if (peek == '/')
{
while (peek != '\n')
{
increasePeek();
}
return null;
}
else if (peek == '*')
{
increasePeek();
do
{
pre = peek;
increasePeek();
}
while (pre != '*' || peek != '/');
peek = ' ';
return null;
}
else
{
return new Token(pre);
}
case '<':
if (peek == '=')
{
peek = ' ';
return new Token(Tag.LESS_OR_EQUAL);
}
else return new Token('<');
case '=':
if (peek == '=')
{
peek = ' ';
return new Token(Tag.EQUAL);
}
else return new Token('=');
case '!':
if (peek == '=')
{
peek = ' ';
return new Token(Tag.NOT_EQUAL);
}
else return new Token('!');
case '>':
if (peek == '=')
{
peek = ' ';
return new Token(Tag.GREATER_OR_EQUAL);
}
else return new Token('>');
default:
return new Token(pre);
}
}
private Token handleDigit()
{
int v = 0;
while (char.IsDigit(peek))
{
v = v * 10 + peek - '0';
increasePeek();
}
if (peek == '.')
{
double f = v;
double mut = 1;
increasePeek();
while (char.IsDigit(peek))
{
mut /= 10;
f += mut * (peek - '0');
increasePeek();
}
return new Float(f);
}
return new Num(v);
}
private Word handleLetter()
{
StringBuilder buffer = new StringBuilder();
do
{
buffer.Append(peek);
increasePeek();
} while (char.IsLetterOrDigit(peek));
string str = buffer.ToString();
if (words.ContainsKey(str))
{
return new Word((Tag)words[str], str);
}
Word w = new Word(Tag.ID, str);
words.Add(w.lexeme, w.tag);
return w;
}
private void reserve(Word t) => words.Add(t.lexeme, t.tag);
public Lexer(Reader _reader)
{
reader = _reader;
peek = ' ';
line = 1;
words = new Hashtable();
reserve(new Word(Tag.TRUE, "true"));
reserve(new Word(Tag.FALSE, "false"));
}
/// <summary>
/// 结束时抛出异常
/// </summary>
/// <returns></returns>
public Token scan()
{
while (true)
{
increPeekToUseful();
if (char.IsDigit(peek) || peek == '.')
{
return handleDigit();
}
if (char.IsLetter(peek))
{
return handleLetter();
}
Token t = handleSigns();
if (t != null) return t;
}
}
}
}