322 lines
10 KiB
C#
322 lines
10 KiB
C#
using PerCederberg.Grammatica.Runtime;
|
|
using System;
|
|
using System.IO;
|
|
using System.Linq;
|
|
|
|
namespace arookas
|
|
{
|
|
class sunParser
|
|
{
|
|
static string[] keywords =
|
|
{
|
|
"import",
|
|
"builtin", "function", "var", "const",
|
|
"if", "while", "do", "for",
|
|
"return", "break", "continue",
|
|
"yield", "exit", "dump", "lock", "unlock", "int", "float", "typeof", "print",
|
|
"true", "false",
|
|
};
|
|
|
|
public sunNode Parse(string file)
|
|
{
|
|
using (var input = new StreamReader(file))
|
|
{
|
|
var parser = new __sunParser(input);
|
|
var node = parser.Parse();
|
|
return CreateAst(file, node);
|
|
}
|
|
}
|
|
|
|
static sunNode CreateAst(string file, Node node)
|
|
{
|
|
var ast = ConvertNode(file, node);
|
|
if (ast == null)
|
|
{
|
|
return null;
|
|
}
|
|
// children
|
|
if (node is Production)
|
|
{
|
|
var production = node as Production;
|
|
for (int i = 0; i < production.Count; ++i)
|
|
{
|
|
var child = CreateAst(file, production[i]);
|
|
if (child != null)
|
|
{
|
|
ast.Add(child);
|
|
}
|
|
}
|
|
}
|
|
// transcience
|
|
switch ((__sunConstants)node.Id)
|
|
{
|
|
case __sunConstants.STATEMENT:
|
|
case __sunConstants.COMPOUND_STATEMENT:
|
|
case __sunConstants.COMPOUND_STATEMENT_ITEM:
|
|
case __sunConstants.ASSIGNMENT_OPERATOR:
|
|
case __sunConstants.BINARY_OPERATOR:
|
|
case __sunConstants.UNARY_OPERATOR:
|
|
case __sunConstants.TERM:
|
|
case __sunConstants.PARAMETER:
|
|
case __sunConstants.ARGUMENT_LIST:
|
|
case __sunConstants.ARGUMENT:
|
|
{
|
|
return Transcient(ast);
|
|
}
|
|
}
|
|
return ast;
|
|
}
|
|
static sunNode ConvertNode(string file, Node node)
|
|
{
|
|
var location = new sunSourceLocation(file, node.StartLine, node.StartColumn);
|
|
string token = null;
|
|
if (node is Token)
|
|
{
|
|
token = (node as Token).Image;
|
|
}
|
|
|
|
// statements
|
|
switch (GetId(node))
|
|
{
|
|
case __sunConstants.SCRIPT: return new sunNode(location);
|
|
case __sunConstants.STATEMENT: return new sunNode(location);
|
|
case __sunConstants.STATEMENT_BLOCK: return new sunStatementBlock(location);
|
|
case __sunConstants.COMPOUND_STATEMENT: return new sunNode(location);
|
|
case __sunConstants.COMPOUND_STATEMENT_ITEM: return new sunNode(location);
|
|
|
|
case __sunConstants.IMPORT_STATEMENT: return new sunImport(location);
|
|
case __sunConstants.NAME_LABEL: return new sunNameLabel(location);
|
|
|
|
case __sunConstants.YIELD_STATEMENT: return new sunYield(location);
|
|
case __sunConstants.EXIT_STATEMENT: return new sunExit(location);
|
|
case __sunConstants.DUMP_STATEMENT: return new sunDump(location);
|
|
case __sunConstants.LOCK_STATEMENT: return new sunLock(location);
|
|
case __sunConstants.UNLOCK_STATEMENT: return new sunUnlock(location);
|
|
case __sunConstants.PRINT_STATEMENT: return new sunPrint(location);
|
|
}
|
|
|
|
// literals
|
|
switch (GetId(node))
|
|
{
|
|
case __sunConstants.INT_NUMBER: return new sunIntLiteral(location, token);
|
|
case __sunConstants.HEX_NUMBER: return new sunHexLiteral(location, token);
|
|
case __sunConstants.DEC_NUMBER: return new sunFloatLiteral(location, token);
|
|
case __sunConstants.STRING: return new sunStringLiteral(location, token);
|
|
case __sunConstants.IDENTIFIER: return new sunIdentifier(location, token);
|
|
case __sunConstants.ELLIPSIS: return new sunEllipsis(location);
|
|
case __sunConstants.TRUE: return new sunTrue(location, token);
|
|
case __sunConstants.FALSE: return new sunFalse(location, token);
|
|
}
|
|
|
|
// operators
|
|
switch (GetId(node))
|
|
{
|
|
case __sunConstants.ADD: return new sunAdd(location);
|
|
case __sunConstants.SUB:
|
|
{
|
|
if (GetId(node.Parent) == __sunConstants.UNARY_OPERATOR)
|
|
{
|
|
return new sunNeg(location);
|
|
}
|
|
return new sunSub(location);
|
|
}
|
|
case __sunConstants.MUL: return new sunMul(location);
|
|
case __sunConstants.DIV: return new sunDiv(location);
|
|
case __sunConstants.MOD: return new sunMod(location);
|
|
|
|
case __sunConstants.BIT_AND: return new sunBitAND(location);
|
|
case __sunConstants.BIT_OR: return new sunBitOR(location);
|
|
case __sunConstants.BIT_LSH: return new sunBitLsh(location);
|
|
case __sunConstants.BIT_RSH: return new sunBitRsh(location);
|
|
|
|
case __sunConstants.LOG_AND: return new sunLogAND(location);
|
|
case __sunConstants.LOG_OR: return new sunLogOR(location);
|
|
case __sunConstants.LOG_NOT: return new sunLogNOT(location);
|
|
|
|
case __sunConstants.EQ: return new sunEq(location);
|
|
case __sunConstants.NEQ: return new sunNtEq(location);
|
|
case __sunConstants.LT: return new sunLt(location);
|
|
case __sunConstants.GT: return new sunGt(location);
|
|
case __sunConstants.LTEQ: return new sunLtEq(location);
|
|
case __sunConstants.GTEQ: return new sunGtEq(location);
|
|
|
|
case __sunConstants.ASSIGN: return new sunAssign(location);
|
|
case __sunConstants.ASSIGN_ADD: return new sunAssignAdd(location);
|
|
case __sunConstants.ASSIGN_SUB: return new sunAssignSub(location);
|
|
case __sunConstants.ASSIGN_MUL: return new sunAssignMul(location);
|
|
case __sunConstants.ASSIGN_DIV: return new sunAssignDiv(location);
|
|
case __sunConstants.ASSIGN_MOD: return new sunAssignMod(location);
|
|
|
|
case __sunConstants.ASSIGN_BIT_AND: return new sunAssignBitAND(location);
|
|
case __sunConstants.ASSIGN_BIT_OR: return new sunAssignBitOR(location);
|
|
case __sunConstants.ASSIGN_BIT_LSH: return new sunAssignBitLsh(location);
|
|
case __sunConstants.ASSIGN_BIT_RSH: return new sunAssignBitRsh(location);
|
|
|
|
case __sunConstants.ASSIGNMENT_OPERATOR: return new sunNode(location);
|
|
case __sunConstants.TERNARY_OPERATOR: return new sunTernaryOperator(location);
|
|
case __sunConstants.BINARY_OPERATOR: return new sunNode(location);
|
|
case __sunConstants.UNARY_OPERATOR: return new sunNode(location);
|
|
}
|
|
|
|
// expressions
|
|
switch (GetId(node))
|
|
{
|
|
case __sunConstants.EXPRESSION: return new sunExpression(location);
|
|
case __sunConstants.OPERAND: return new sunOperand(location);
|
|
case __sunConstants.TERM: return new sunNode(location);
|
|
|
|
case __sunConstants.UNARY_OPERATOR_LIST: return new sunUnaryOperatorList(location);
|
|
|
|
case __sunConstants.INT_CAST: return new sunIntCast(location);
|
|
case __sunConstants.FLOAT_CAST: return new sunFloatCast(location);
|
|
case __sunConstants.TYPEOF_CAST: return new sunTypeofCast(location);
|
|
}
|
|
|
|
// builtins
|
|
switch (GetId(node))
|
|
{
|
|
case __sunConstants.BUILTIN_DECLARATION: return new sunBuiltinDeclaration(location);
|
|
}
|
|
|
|
// functions
|
|
switch (GetId(node))
|
|
{
|
|
case __sunConstants.FUNCTION_DEFINITION: return new sunFunctionDefinition(location);
|
|
case __sunConstants.FUNCTION_CALL: return new sunFunctionCall(location);
|
|
|
|
case __sunConstants.PARAMETER_LIST: return new sunParameterList(location);
|
|
case __sunConstants.PARAMETER: return new sunNode(location);
|
|
case __sunConstants.ARGUMENT_LIST: return new sunNode(location);
|
|
case __sunConstants.ARGUMENT: return new sunNode(location);
|
|
}
|
|
|
|
// variables
|
|
switch (GetId(node))
|
|
{
|
|
case __sunConstants.VARIABLE_REFERENCE: return new sunVariableReference(location);
|
|
case __sunConstants.VARIABLE_DECLARATION: return new sunVariableDeclaration(location);
|
|
case __sunConstants.VARIABLE_DEFINITION: return new sunVariableDefinition(location);
|
|
case __sunConstants.VARIABLE_ASSIGNMENT: return new sunVariableAssignment(location);
|
|
}
|
|
|
|
// constants
|
|
switch (GetId(node))
|
|
{
|
|
case __sunConstants.CONST_DEFINITION: return new sunConstDefinition(location);
|
|
}
|
|
|
|
// flow control
|
|
switch (GetId(node))
|
|
{
|
|
case __sunConstants.IF_STATEMENT: return new sunIf(location);
|
|
case __sunConstants.WHILE_STATEMENT: return new sunWhile(location);
|
|
case __sunConstants.DO_STATEMENT: return new sunDo(location);
|
|
case __sunConstants.FOR_STATEMENT: return new sunFor(location);
|
|
case __sunConstants.FOR_DECLARATION: return new sunForDeclaration(location);
|
|
case __sunConstants.FOR_CONDITION: return new sunForCondition(location);
|
|
case __sunConstants.FOR_ITERATION: return new sunForIteration(location);
|
|
|
|
case __sunConstants.RETURN_STATEMENT: return new sunReturn(location);
|
|
case __sunConstants.BREAK_STATEMENT: return new sunBreak(location);
|
|
case __sunConstants.CONTINUE_STATEMENT: return new sunContinue(location);
|
|
}
|
|
|
|
// cleanup keywords punctuation
|
|
switch (GetId(node))
|
|
{
|
|
// keywords
|
|
case __sunConstants.IMPORT:
|
|
case __sunConstants.BUILTIN:
|
|
case __sunConstants.FUNCTION:
|
|
case __sunConstants.VAR:
|
|
case __sunConstants.CONST:
|
|
|
|
case __sunConstants.IF:
|
|
case __sunConstants.ELSE:
|
|
case __sunConstants.DO:
|
|
case __sunConstants.WHILE:
|
|
case __sunConstants.FOR:
|
|
|
|
case __sunConstants.RETURN:
|
|
case __sunConstants.BREAK:
|
|
case __sunConstants.CONTINUE:
|
|
|
|
case __sunConstants.YIELD:
|
|
case __sunConstants.EXIT:
|
|
case __sunConstants.DUMP:
|
|
case __sunConstants.LOCK:
|
|
case __sunConstants.UNLOCK:
|
|
case __sunConstants.INT:
|
|
case __sunConstants.FLOAT:
|
|
case __sunConstants.TYPEOF:
|
|
case __sunConstants.PRINT:
|
|
|
|
case __sunConstants.TRUE:
|
|
case __sunConstants.FALSE:
|
|
|
|
// punctuation
|
|
case __sunConstants.L_BRACE:
|
|
case __sunConstants.R_BRACE:
|
|
case __sunConstants.L_PAREN:
|
|
case __sunConstants.R_PAREN:
|
|
case __sunConstants.L_BRACKET:
|
|
case __sunConstants.R_BRACKET:
|
|
case __sunConstants.COLON:
|
|
case __sunConstants.SEMICOLON:
|
|
case __sunConstants.COMMA:
|
|
case __sunConstants.DOT:
|
|
// case __sunConstants.ELLIPSIS: // do not exclude ellipsis for variadic parameters
|
|
case __sunConstants.QMARK:
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// emergency fallback
|
|
return null;
|
|
}
|
|
static sunSourceLocation GetSourceLocation(string file, Node node)
|
|
{
|
|
if (file == null)
|
|
{
|
|
throw new ArgumentNullException("file");
|
|
}
|
|
if (node == null)
|
|
{
|
|
throw new ArgumentNullException("node");
|
|
}
|
|
if (node is Production)
|
|
{
|
|
var production = node as Production;
|
|
if (production.Count > 0)
|
|
{
|
|
return GetSourceLocation(file, production[0]);
|
|
}
|
|
throw new ArgumentException("node is a child-less production.", "node");
|
|
}
|
|
else if (node is Token)
|
|
{
|
|
var token = node as Token;
|
|
return new sunSourceLocation(file, token.StartLine, token.StartColumn);
|
|
}
|
|
throw new ArgumentException("node is an unsupported type.", "node");
|
|
}
|
|
static sunNode Transcient(sunNode node)
|
|
{
|
|
if (node == null)
|
|
{
|
|
throw new ArgumentNullException("node");
|
|
}
|
|
return node.Count == 1 ? node[0] : node;
|
|
}
|
|
static __sunConstants GetId(Node node)
|
|
{
|
|
return (__sunConstants)node.Id;
|
|
}
|
|
|
|
public static bool IsKeyword(string name)
|
|
{
|
|
return keywords.Contains(name);
|
|
}
|
|
}
|
|
}
|