Dies ist eine alte Version des Dokuments!
TinyPG
<% @TinyPG Language="c#" OutputPath="C:\chroot\Parser\" %>
NUMBER -> @"[0-9]+";
PLUSMINUS -> @"(\+|-)";
MULTDIV -> @"\*|/";
BROPEN -> @"\(";
BRCLOSE -> @"\)";
EOF -> @"^$";
[Skip] WHITESPACE -> @"\s+";
Start -> (AddExpr)? EOF;
AddExpr -> MultExpr (PLUSMINUS MultExpr)*;
MultExpr -> Atom (MULTDIV Atom)*;
Atom -> NUMBER | BROPEN AddExpr BRCLOSE;
// Simple expression calculator with print + strings + variables
<% @TinyPG Language="C#" Namespace="MyScript" OutputPath="C:\Users\manuel.zarat\source\repos\ConsoleApp1\ConsoleApp1\" %>
// -------- Tokens --------
EOF -> @"^\s*$";
[Color(255, 0, 0)] NUMBER -> @"[0-9]+";
[Color(163, 21, 21)] STRING -> @"""[^""]*""";
[Color(128, 0, 128)] PRINT -> @"print";
[Color(0, 128, 0)] IDENT -> @"[a-zA-Z_][a-zA-Z0-9_]*";
[Color(0, 0, 255)] ASSIGN -> @"=";
[Color(0, 0, 255)] PLUSMINUS -> @"(\+|-)";
[Color(0, 0, 255)] MULTDIV -> @"\*|/";
[Color(0, 0, 255)] BROPEN -> @"\(";
[Color(0, 0, 255)] BRCLOSE -> @"\)";
[Skip] WHITESPACE -> @"\s+";
// =======================
// Grammatik / Semantik
// =======================
// mehrere Statements; Result ist uns egal -> null
Start -> (Statement)* EOF
{
string output = "";
int i = 0;
while ($Statement[i] != null) {
if ($Statement[i] != null) {
if (output.Length > 0)
output += "\r\n";
output += $Statement[i].ToString();
}
i++;
}
return output;
};
Statement -> AssignStmt | PrintStmt | ExprStmt
{
if ($AssignStmt != null) return $AssignStmt;
if ($PrintStmt != null) return $PrintStmt;
return $ExprStmt;
};
// a = 12 oder a = "Hallo" oder a = 1+2*3
AssignStmt -> IDENT ASSIGN AddExpr
{
// "Variables" kommt aus der partiellen Parser-Klasse (siehe unten)
Variables[$IDENT.ToString()] = $AddExpr;
return null;
};
// print( Ausdruck )
PrintStmt -> PRINT BROPEN AddExpr BRCLOSE
{
Console.WriteLine($AddExpr);
return null;
};
// nackter Ausdruck als Statement
ExprStmt -> AddExpr
{
return $AddExpr;
};
// Addition / Subtraktion
// +: Zahlen addieren ODER Strings konkatenieren
AddExpr -> MultExpr (PLUSMINUS MultExpr)*
{
object value = $MultExpr;
int i = 1;
while ($MultExpr[i] != null)
{
string sign = $PLUSMINUS[i-1].ToString();
object rhs = $MultExpr[i++];
if (sign == "+")
{
if (value is string || rhs is string)
value = value.ToString() + rhs.ToString();
else
value = Convert.ToInt32(value) + Convert.ToInt32(rhs);
}
else // "-"
{
value = Convert.ToInt32(value) - Convert.ToInt32(rhs);
}
}
return value;
};
// Multiplikation / Division (nur numerisch)
MultExpr -> Atom (MULTDIV Atom)*
{
object value = $Atom;
int i = 1;
while ($Atom[i] != null)
{
string sign = $MULTDIV[i-1].ToString();
object rhs = $Atom[i++];
if (sign == "*")
{
value = Convert.ToInt32(value) * Convert.ToInt32(rhs);
}
else // "/"
{
value = Convert.ToInt32(value) / Convert.ToInt32(rhs);
}
}
return value;
};
// Atome: Zahl, String, Variable oder (Ausdruck)
Atom -> NUMBER | STRING | IDENT | BROPEN AddExpr BRCLOSE
{
if ($NUMBER != null)
{
return Convert.ToInt32($NUMBER.ToString());
}
else if ($STRING != null)
{
string s = $STRING.ToString();
if (s.Length >= 2 && s[0] == '"' && s[s.Length - 1] == '"')
s = s.Substring(1, s.Length - 2);
return s;
}
else if ($IDENT != null)
{
// Variable lesen
object v;
string name = $IDENT.ToString();
if (!Variables.TryGetValue(name, out v))
throw new Exception("Variable '" + name + "' ist nicht definiert.");
return name;
}
else
{
// ( Ausdruck )
return $AddExpr;
}
};