Skip to content

Instantly share code, notes, and snippets.

@amieres
Last active August 29, 2015 14:01
Show Gist options
  • Save amieres/c61c9da3055ff7dc3b1b to your computer and use it in GitHub Desktop.
Save amieres/c61c9da3055ff7dc3b1b to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
namespace SimpleParser {
class Parser {
public Parser(string Text) {
Input = Text;
}
#region Lexer Section
String Input = null;
public int Position = 0;
String Token = null;
int LastPosition = -1;
int SpaceLength = 0;
string CurrentString;
void SkipSpacesComments() {
if (Position == LastPosition) return;
LastPosition = Position;
CurrentString = Input.Substring(Position);
string RegEx = "^([ \\t\\n\\r]|\\/\\*.*?\\*\\/)*";
Match M = Regex.Match(CurrentString, RegEx);
SpaceLength = M.Length;
if (SpaceLength > 0)
CurrentString = CurrentString.Substring(SpaceLength);
}
bool R(string RegEx) {
SkipSpacesComments();
Match M = Regex.Match(CurrentString, "^" + RegEx, RegexOptions.IgnoreCase);
if (M.Success) {
Token = CurrentString.Substring(0, M.Length);
Position += M.Length + SpaceLength;
}
return M.Success;
}
bool W(string C) {
return R(C + "\\b"); // whole words only
}
bool C(string C) {
return R(Regex.Escape(C));
}
#endregion
#region Parser Section
public bool Stopping = false;
bool P(rule R) {
if (Stopping) return false;
int StartingPosition = Position;
bool Result = R();
if (!Result && StartingPosition != Position)
Stopping = true;
return Result;
}
delegate bool rule();
delegate bool ruleL(int L);
#endregion
#region grammar section
ruleL expr, expr2;
rule wexpr, mexpr, whexp, whexp2, id2, list, list2;
rule NUMBER, ID, EOS, NIL;
public bool Parse() {
wexpr = () => P(() => expr(0) && EOS() );
expr = (L) => P(() => mexpr() && expr2(L) );
expr2 = (L) => P(() => L < 4 && C("+") && expr(4) && expr2(L) )
|| P(() => L < 4 && C("-") && expr(4) && expr2(L) )
|| P(() => L < 5 && C("*") && expr(5) && expr2(L) )
|| P(() => L < 5 && C("/") && expr(5) && expr2(L) )
|| P(() => L < 2 && C("<=") && expr(2) && expr2(L) )
|| P(() => L < 2 && C(">=") && expr(2) && expr2(L) )
|| P(() => L < 2 && C("<>") && expr(2) && expr2(L) )
|| P(() => L < 2 && C("=") && expr(2) && expr2(L) )
|| P(() => L < 2 && C("<") && expr(2) && expr2(L) )
|| P(() => L < 2 && C(">") && expr(2) && expr2(L) )
|| P(() => L < 1 && W("AND") && expr(1) && expr2(L) )
|| P(() => L < 1 && W("OR") && expr(1) && expr2(L) )
|| P(() => NIL() );
mexpr = () => P(() => C("-") && expr(9) )
|| P(() => C("+") && expr(9) )
|| P(() => W("NOT") && expr(9) )
|| P(() => C("(") && expr(0) && C(")") )
|| P(() => W("CASE") && whexp() && W("END") )
|| P(() => NUMBER() )
|| P(() => ID() && id2() );
whexp = () => P(() => W("WHEN") && expr(0) && W("THEN") && expr(0) && whexp2() );
whexp2 = () => P(() => whexp() )
|| P(() => W("ELSE") && expr(0) )
|| P(() => NIL() );
id2 = () => P(() => C("(") && list() && C(")") )
|| P(() => NIL() );
list = () => P(() => expr(0) && list2() )
|| P(() => NIL() );
list2 = () => P(() => C(",") && expr(0) && list2() )
|| P(() => NIL() );
ID = () => R("[a-z][a-z0-9_]*");
NUMBER = () => R("([0-9]+(\\.[0-9]*|)|\\.[0-9]+)");
EOS = () => R("$");
NIL = () => true;
return wexpr();
}
#endregion
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment