} // set during AST construction #region implemented abstract members of Node /// <summary> /// Resolve type defined by this typeExpression. Type Expression must be given in reversed order. /// </summary> /// <returns>The resolved type.</returns> /// <param name="typeExpr">Enumerator of reversed type expresion enumeration.</param> public static TypeNode RecursiveResolveArrayType <TSymbol>(IEnumerator <IParseTree <TSymbol> > typeExpr) where TSymbol : ISymbol <TSymbol> { bool isMutable = ASTBuilder.EatSymbol("mutable", typeExpr); if (ASTBuilder.EatSymbol("]", typeExpr)) // if ] is present then create ArrayType { var resType = new ArrayTypeNode(); resType.IsConstant = !isMutable; resType.IsFixedSize = false; // we initialize all arrays as dynamic size if (ASTBuilder.EatSymbol("[", typeExpr)) // opening bracket, no length expression { resType.LengthExpression = null; } else // length expression present { resType.LengthExpression = ExpressionNode.GetExpressionNode(typeExpr.Current); typeExpr.MoveNext(); Debug.Assert(ASTBuilder.EatSymbol("[", typeExpr)); // eat opening bracket } resType.ElementType = RecursiveResolveArrayType(typeExpr); return(resType); } else { var resType = new NamedTypeNode(); resType.BuildNode(typeExpr.Current); resType.IsConstant = !isMutable; return(resType); } }
public static ExpressionNode ResolveOperatorExpression <TSymbol>(IParseTree <TSymbol> parseTree, int opLevel) where TSymbol : ISymbol <TSymbol> { if (opLevel > OP_BOTTOM_LEVEL) { // these part proceeds op from level 15 to 5 bool isLeft = ASTBuilder.IsLeftOperator(parseTree.Symbol); // get childrens connected by operators (one level lower) var childs = isLeft ? ASTBuilder.Children(parseTree).Reverse().GetEnumerator() : // if left-to-right then reverse arguments ASTBuilder.Children(parseTree).GetEnumerator(); Debug.Assert(childs.MoveNext()); // set enumerator to the first element (must be present) return(ParseBinOperator(childs, opLevel - 1, isLeft)); } else { // continue parsing lower level expressions Debug.Assert(opLevel == OP_BOTTOM_LEVEL); // op level must be 4 var node = ASTBuilder.FirstChild(parseTree); // Operator4Expression -> Operator3Expression // Operator3Expression -> (prefix_operator)* Operator2Expression var childs = ASTBuilder.Children(node).Reverse().GetEnumerator(); Debug.Assert(childs.MoveNext()); var op2 = childs.Current; // last child -> Operator2Expression var op2Childs = ASTBuilder.RevChildrenEnumerator(op2); Debug.Assert(op2Childs.MoveNext()); return(AddPrefixOperators(3, ParseOperator2(op2Childs), childs)); } }
} // set during AST construction #region implemented abstract members of Node public override void BuildNode <TSymbol>(IParseTree <TSymbol> parseTree) { // LoopControl -> ("break" | "continue") (Expression DecimalNumberLiteral?)? var childs = ASTBuilder.ChildrenArray(parseTree); Debug.Assert(childs.Length >= 1); switch (childs[0].Fragment.GetOriginText()) { case "break": Mode = LoopControlMode.LCM_BREAK; break; case "continue": Mode = LoopControlMode.LCM_CONTINUE; break; } if (childs.Length >= 2) { Value = ExpressionNode.GetExpressionNode(childs[1]); } if (childs.Length == 3) { Depth = int.Parse(childs[2].Fragment.GetOriginText()); } }
public override void BuildNode <TSymbol>(IParseTree <TSymbol> parseTree) { // DecimalNumberLiteral -> DecimalNumberLiteralToken // CharacterLiteral -> CharacterLiteralToken // BooleanLiteral -> BooleanLiteralToken Value = ASTBuilder.FirstChild(parseTree).Fragment.GetOriginText(); // fill only value - type was set during construction }
public static ConstNode GetConstNode <TSymbol>(IParseTree <TSymbol> parseTree) where TSymbol : ISymbol <TSymbol> { // one of: DecimalNumberLiteral | CharacterLiteral | StringLiteral | BooleanLiteral TypeNode type; switch (ASTBuilder.GetName(parseTree.Symbol)) { case "DecimalNumberLiteral": type = NamedTypeNode.IntType(true); break; case "CharacterLiteral": type = NamedTypeNode.CharType(true); break; case "StringLiteral": throw new NotImplementedException(); // TODO: strings implementation case "BooleanLiteral": type = NamedTypeNode.BoolType(true); break; default: throw new System.ArgumentException(); } return(new AtomNode(type)); }
public override void BuildNode <TSymbol> (IParseTree <TSymbol> parseTree) { var arr = ASTBuilder.ChildrenArray(parseTree); FieldName = arr [0].Fragment.GetOriginText(); Value = ExpressionNode.GetExpressionNode(arr [2]); }
} // set during AST construction #region implemented abstract members of Node // RecordFieldDefinition.SetProduction(ObjectDeclaration * ";"); // ObjectDeclaration.SetProduction(TypeSpecifier * ObjectName); public override void BuildNode <TSymbol>(IParseTree <TSymbol> parseTree) { IParseTree <TSymbol>[] childs = ASTBuilder.ChildrenArray(parseTree); // type name Debug.Assert(childs.Length == 2); Type = TypeNode.GetTypeNode(childs[0]); // type - arg 0 Name = childs[1].Fragment.GetOriginText(); // name - arg 1 }
// TypeSpecifier -> (TypeName * ("mutable".Optional() * "\\[" * Expression.Optional * "\\]").Star * "mutable".Optional()); public static TypeNode GetTypeNode <TSymbol>(IParseTree <TSymbol> parseTree) where TSymbol : ISymbol <TSymbol> { var node = ASTBuilder.AsBranch(parseTree); var childs = node.Children.Reverse().GetEnumerator(); Debug.Assert(childs.MoveNext()); return(RecursiveResolveArrayType(childs)); }
} // name resolution #region implemented abstract members of Node public override void BuildNode <TSymbol> (IParseTree <TSymbol> parseTree) { // <recordName> [ <field> ] var children = ASTBuilder.ChildrenArray(parseTree); RecordName = children [0].Fragment.GetOriginText(); Field = children [2].Fragment.GetOriginText(); }
public override void BuildNode <TSymbol>(IParseTree <TSymbol> parseTree) { // ObjectDefinition -> TypeSpecifier ObjectName "=" Expression var childs = ASTBuilder.ChildrenArray(parseTree); Debug.Assert(childs.Length == 4); Type = TypeNode.GetTypeNode(childs[0]); // type - arg 0 Name = childs[1].Fragment.GetOriginText(); // name - arg 1 Value = ExpressionNode.GetExpressionNode(childs[3]); // value - arg 3 }
public override void BuildNode <TSymbol> (IParseTree <TSymbol> parseTree) { Console.WriteLine("Build ast: " + parseTree); IParseTree <TSymbol>[] childs = ASTBuilder.ChildrenArray(parseTree); // name { fields } Debug.Assert(childs.Length == 4); // name from arg 0 Name = TypeNode.GetTypeNode(childs[0]); // fields from arg 2 Fields = GetFields(childs[2]); }
public override void BuildNode <TSymbol> (IParseTree <TSymbol> parseTree) { // <type> <name> { <fields> } var children = ASTBuilder.ChildrenArray(parseTree); Debug.Assert(children.Length == 5); Type = TypeNode.GetTypeNode(children[0]); // type - arg 0 Name = children[1].Fragment.GetOriginText(); // name - arg 1 Fields = GetFields(children [3]); // fields - arg 3 }
public override void BuildNode <TSymbol>(IParseTree <TSymbol> parseTree) { // IfExpression -> "if" Expression Expression ("else" Expression)? var childs = ASTBuilder.ChildrenArray(parseTree); Debug.Assert(childs.Length >= 3); Condition = ExpressionNode.GetExpressionNode(childs[1]); Then = ExpressionNode.GetExpressionNode(childs[2]); if (childs.Length == 5) { Else = ExpressionNode.GetExpressionNode(childs[4]); } }
} // set during AST construction #region implemented abstract members of Node public IEnumerable <RecordVariableFieldDefNode> GetFields <TSymbol> (IParseTree <TSymbol> parseTree) where TSymbol : ISymbol <TSymbol> { var lst = new LinkedList <RecordVariableFieldDefNode> (); var childs = ASTBuilder.ChildrenEnumerator(parseTree); while (childs.MoveNext()) { var v = new RecordVariableFieldDefNode(); v.BuildNode(childs.Current); lst.AddLast(v); childs.MoveNext(); // skip ',' if present } return(lst); }
// ----- Methods ----- #region implemented abstract members of Node private IEnumerable <VariableDeclNode> GetParameters <TSymbol>(IParseTree <TSymbol> parseTree) where TSymbol : ISymbol <TSymbol> { var parList = new LinkedList <VariableDeclNode>(); var childs = ASTBuilder.ChildrenEnumerator(parseTree); while (childs.MoveNext()) { var par = new VariableDeclNode(); par.BuildNode(childs.Current); parList.AddLast(par); childs.MoveNext(); // skip ',' if present } return(parList); }
public override void BuildNode <TSymbol>(IParseTree <TSymbol> parseTree) { IParseTree <TSymbol>[] childs = ASTBuilder.ChildrenArray(parseTree); // name ( params ) -> type expr Debug.Assert(childs.Length == 7); // name from arg 0 Name = childs[0].Fragment.GetOriginText(); // parameters from arg 2 Parameters = GetParameters(childs[2]); // type from arg 5 ResultType = TypeNode.GetTypeNode(childs[5]); // body from arg 6 Body = ExpressionNode.GetExpressionNode(childs[6]); }
static IEnumerable <RecordTypeFieldDeclarationNode> GetFields <TSymbol>(IParseTree <TSymbol> parseTree) where TSymbol : ISymbol <TSymbol> { var lst = new LinkedList <RecordTypeFieldDeclarationNode>(); var childs = ASTBuilder.ChildrenEnumerator(parseTree); while (childs.MoveNext()) { var objectDefinition = ASTBuilder.ChildrenArray(childs.Current) [0]; var fld = new RecordTypeFieldDeclarationNode(); fld.BuildNode(objectDefinition); lst.AddLast(fld); } return(lst); }
/// <summary> /// Resolve Expression from ParseTree. Main method. /// </summary> public static ExpressionNode GetExpressionNode <TSymbol>(IParseTree <TSymbol> parseTree) where TSymbol : ISymbol <TSymbol> { var node = ASTBuilder.FirstChild(parseTree); // Expression -> RecordVariableDefinitionExpression | RecordFieldAccessExpression | OperatorExpression if (ASTBuilder.GetName(node.Symbol) == "RecordVariableDefinitionExpression") { var nod = new RecordVariableDefNode(); nod.BuildNode(node); return(nod); } if (ASTBuilder.GetName(node.Symbol) == "RecordFieldAccessExpression") { var nod = new RecordVariableFieldUseNode(); nod.BuildNode(node); return(nod); } node = ASTBuilder.FirstChild(node); // OperatorExpression -> Operator19Expression node = ASTBuilder.FirstChild(node); // Operator19Expression -> ObjectDefinitionExpression | Operator18Expression if (ASTBuilder.GetName(node.Symbol) == "ObjectDefinitionExpression") // ObjectDefinition { var defNode = new VariableDefNode(); defNode.BuildNode(node); return(defNode); } // Operator18Expression node = ASTBuilder.FirstChild(node); // IfExpression | WhileExpression | Operator17Expression switch (ASTBuilder.GetName(node.Symbol)) { case "IfExpression": var ifNode = new IfNode(); ifNode.BuildNode(node); return(ifNode); case "WhileExpression": var whileNode = new WhileNode(); whileNode.BuildNode(node); return(whileNode); default: // default - Operator17Expression break; } node = ASTBuilder.FirstChild(node); // Operator17Expression -> Operator16Expression node = ASTBuilder.FirstChild(node); // Operator16Expression -> Operator15Expression return(ResolveOperatorExpression(node, 15)); // node is operator 15 }
} // set during AST construction #region implemented abstract members of Node public override void BuildNode <TSymbol>(IParseTree <TSymbol> parseTree) { // Block -> "{" (Expression ";")* "}" var childs = ASTBuilder.ChildrenEnumerator(parseTree); childs.MoveNext(); // go to "{" Debug.Assert(childs.MoveNext()); // enter the brackets var elems = new List <ExpressionNode>(); while (!ASTBuilder.EatSymbol("}", childs)) // collect expressions until closing "}" { elems.Add(ExpressionNode.GetExpressionNode(childs.Current)); childs.MoveNext(); // go to the next symbol Debug.Assert(ASTBuilder.EatSymbol(";", childs)); // it must be ";" } Elements = elems; }
public static ExpressionNode ResolveAtomicExpression <TSymbol>(IParseTree <TSymbol> parseTree) where TSymbol : ISymbol <TSymbol> { // AtomicExpression -> BlockExpression | ObjectDefinitionExpression | ArrayLiteralExpression | ObjectUseExpression | // IfExpression | WhileExpression | LoopControlExpression var node = ASTBuilder.FirstChild(parseTree); // AtomicExpression -> one of available symbols ExpressionNode atomic; switch (ASTBuilder.GetName(node.Symbol)) { case "BlockExpression": atomic = new BlockExpressionNode(); break; case "ArrayLiteralExpression": throw new System.NotImplementedException(); // TODO: arrays implementation case "ObjectUseExpression": // ObjectUseExpression -> ObjectName | Literals node = ASTBuilder.FirstChild(node); if (node.Symbol.IsTerminal) // ObjectName { atomic = new VariableUseNode(); } else // Literals { node = ASTBuilder.FirstChild(node); // Literals -> one of available literals atomic = ConstNode.GetConstNode(node); } break; case "LoopControlExpression": atomic = new LoopControlNode(); break; default: throw new System.ArgumentException(); } atomic.BuildNode(node); return(atomic); }
// ----- Methods ----- #region implemented abstract members of Node // Program -> (Function|Record)* Eof public override void BuildNode <TSymbol>(IParseTree <TSymbol> parseTree) { var childs = ASTBuilder.ChildrenArray(parseTree); for (int i = 0; i < childs.Length - 1; i++) // skip last child - it is EOF { switch (ASTBuilder.GetName(childs [i].Symbol)) { case "RecordTypeDeclaration": var recordNode = new RecordTypeDeclarationNode(); recordNode.BuildNode(childs [i]); records.AddLast(recordNode); break; default: var funNode = new FunctionDefinitionNode(); funNode.BuildNode(childs [i]); functions.AddLast(funNode); break; } } }
/// <summary> /// Parse one line expression with ++ -- (postfix), function call, array subscript, slice subscript operators. /// Enumerator must be given with reversed ordering of arguments. This corresponds to Operator2Expression from Grammar. /// </summary> public static ExpressionNode ParseOperator2 <TSymbol>(IEnumerator <IParseTree <TSymbol> > opExpr) where TSymbol : ISymbol <TSymbol> { // O2 -> O1 ( "++" | "--" // | "(" (E ",")* E? ")" // | "[" E "]" // | "[" E? ".." E? "]" // )* if (opExpr.Current.Symbol.IsTerminal) { string curText = ASTBuilder.EatTerminal(opExpr); switch (curText) { case "++": case "--": return(OperatorNode.BuildUnaryOperator(2, curText, ParseOperator2(opExpr))); case ")": var args = new LinkedList <ExpressionNode>(); while (!ASTBuilder.EatSymbol("(", opExpr)) { ASTBuilder.EatSymbol(",", opExpr); // eat ',' before arg - f(x,y,z,) is also possible args.AddFirst(GetExpressionNode(opExpr.Current)); opExpr.MoveNext(); // move to next param with ',' } var res = new FunctionCallNode(); res.Arguments = new List <ExpressionNode>(args); // TODO: can something return a 'pointer' to function which we can call to execute? res.Name = opExpr.Current.Fragment.GetOriginText(); return(res); case "]": var toExpr = ASTBuilder.EatNonTerminal(opExpr); // slice to or index bool isSlice = ASTBuilder.EatSymbol("..", opExpr); var fromExpr = ASTBuilder.EatNonTerminal(opExpr); Debug.Assert(ASTBuilder.EatSymbol("[", opExpr)); if (isSlice) // slice subscript { return(SliceNode.CreateSliceNode(ParseOperator2(opExpr), GetExpressionOrNull(fromExpr), GetExpressionOrNull(toExpr))); } else // array subscript { return(ElementNode.Create(ParseOperator2(opExpr), GetExpressionNode(toExpr))); } default: Debug.Assert(false); break; } } else // non-terminal -> Operator1Expression { var op1 = opExpr.Current; Debug.Assert(!opExpr.MoveNext()); // it must be final symbol in this enumeration var node = ASTBuilder.FirstChild(op1); // Operator1Expression -> Operator0Expression // Operator0Expression -> AtomicExpression | "(" Expression ")"; var childs = ASTBuilder.ChildrenEnumerator(node); Debug.Assert(childs.MoveNext()); if (ASTBuilder.EatSymbol("(", childs)) { return(GetExpressionNode(childs.Current)); // Expression } else // proceed with AtomicExpression { return(ResolveAtomicExpression(childs.Current)); } } return(null); }