Dies ist eine alte Version des Dokuments!
TinyPG
//@TinyPG - a Tiny Parser Generator v1.2
// Mini-Skriptsprache: print, Variablen, while
<% @TinyPG Language="C#" Namespace="MyScript" OutputPath="C:\Users\manuel.zarat\source\repos\ConsoleApp1\ConsoleApp1" %>
// Tokens (Reihenfolge ist wichtig!)
EOF -> @"^\s*$";
[Color(255, 0, 0)] NUMBER -> @"[0-9]+";
[Color(0, 0, 255)] PLUSMINUS -> @"(\+|-)";
[Color(0, 0, 255)] MULTDIV -> @"\*|/";
[Color(0, 0, 255)] BROPEN -> @"\(";
[Color(0, 0, 255)] BRCLOSE -> @"\)";
[Color(0, 0, 255)] ASSIGN -> @"=";
// Keywords – MÜSSEN VOR IDENT kommen!
[Color(0, 128, 0)] PRINT -> @"print";
[Color(0, 128, 0)] LET -> @"let";
[Color(0, 128, 0)] WHILE -> @"while";
[Color(0, 128, 0)] DO -> @"do";
[Color(0, 128, 0)] END -> @"end";
// Bezeichner
[Color(128, 0, 128)] IDENT -> @"[a-zA-Z_][a-zA-Z0-9_]*";
[Skip] WHITESPACE -> @"\s+";
// --------- Grammatik ---------
// Ein Programm ist eine Liste von Statements
Start -> StmtList EOF
{
return $StmtList;
};
// Liste von Statements
StmtList -> (Stmt)*
{
// WICHTIG: wir laufen direkt über die Kindknoten,
// damit jedes Stmt genau einmal evaluiert wird.
foreach (ParseNode node in nodes)
{
if (node.Token.Type == TokenType.Stmt)
node.Eval(tree);
}
return null;
};
// Ein Statement kann print, let oder while sein
Stmt -> PrintStmt
| LetStmt
| WhileStmt
;
// print-Ausgabe
PrintStmt -> PRINT AddExpr
{
int value = Convert.ToInt32($AddExpr);
Console.WriteLine(value);
return null;
};
// Variablenzuweisung: let x = 3+4
LetStmt -> LET IDENT ASSIGN AddExpr
{
string name = $IDENT.ToString();
int value = Convert.ToInt32($AddExpr);
if (!tree.Variables.ContainsKey(name))
tree.Variables.Add(name, value);
else
tree.Variables[name] = value;
return null;
};
// while-Schleife: while <expr> do <stmts> end
// Schleife läuft, solange Ausdruck != 0 ist
WhileStmt -> WHILE AddExpr DO StmtList END
{
while (Convert.ToInt32($AddExpr) != 0)
{
// Body neu ausführen
$StmtList;
}
return null;
};
// ---------- Ausdrücke ----------
AddExpr -> MultExpr (PLUSMINUS MultExpr)*
{
int Value = Convert.ToInt32($MultExpr);
int i = 1;
while ($MultExpr[i] != null)
{
string sign = $PLUSMINUS[i-1].ToString();
if (sign == "+")
Value += Convert.ToInt32($MultExpr[i++]);
else
Value -= Convert.ToInt32($MultExpr[i++]);
}
return Value;
};
MultExpr -> Atom (MULTDIV Atom)*
{
int Value = Convert.ToInt32($Atom);
int i = 1;
while ($Atom[i] != null)
{
string sign = $MULTDIV[i-1].ToString();
if (sign == "*")
Value *= Convert.ToInt32($Atom[i++]);
else
Value /= Convert.ToInt32($Atom[i++]);
}
return Value;
};
// Atom: Zahl, Variable oder (Ausdruck)
Atom -> NUMBER | IDENT | BROPEN AddExpr BRCLOSE
{
if ($NUMBER != null)
return $NUMBER;
if ($IDENT != null)
{
string name = $IDENT.ToString();
if (tree.Variables.ContainsKey(name))
return tree.Variables[name];
else
throw new Exception("Undefined variable: " + name);
}
// Klammer-Ausdruck
return $AddExpr;
};