private static SemanticInfo RegisterModelType(Type modelType) { using (new Tracer(modelType)) { SemanticInfo semanticInfo = ExtractSemanticInfo(modelType); _modelTypeToSemanticInfoMapping.Add(modelType, semanticInfo); foreach (string semanticTypeName in semanticInfo.MappedSemanticTypes) { ISet <Type> mappedModelTypes; if (!_semanticTypeToModelTypesMapping.TryGetValue(semanticTypeName, out mappedModelTypes)) { mappedModelTypes = new HashSet <Type>(); _semanticTypeToModelTypesMapping.Add(semanticTypeName, mappedModelTypes); } mappedModelTypes.Add(modelType); } if (semanticInfo.PublicSemanticTypes.Any()) { Log.Debug("Model type '{0}' has semantic type(s) '{1}'.", modelType.FullName, string.Join(" ", semanticInfo.PublicSemanticTypes)); foreach (KeyValuePair <string, IList <string> > kvp in semanticInfo.SemanticProperties) { Log.Debug("\tRegistered property '{0}' as semantic property '{1}'", kvp.Key, string.Join(" ", kvp.Value)); } } return(semanticInfo); } }
public ExpressionNode(IToken token) : base(token) { ///instanciamos el NodeInfo NodeInfo = new SemanticInfo(); LoadVariableInTheStack = true; }
public override void CheckSignatureSemantic(SymbolTable symbolTable, List <CompileError> errors) { SemanticInfo typeInfo; ///el tipo no puede estar definido if (symbolTable.GetDefinedTypeShallow(TypeId, out typeInfo)) { errors.Add(new CompileError { Line = this.Line, Column = this.CharPositionInLine, ErrorMessage = string.Format("Current context already contains a definition for '{0}'", TypeId), Kind = ErrorKind.Semantic }); ///el nodo evalúa de error NodeInfo = SemanticInfo.SemanticError; return; } typeInfo = new SemanticInfo { Name = TypeId, ElementKind = SymbolKind.Type, //Type = null, IsPending = true }; typeInfo.Type = !(this is AliasDeclarationNode) ? typeInfo : null; ///insertamos el tipo en la tabla de símbolos como pendiente symbolTable.InsertSymbol(typeInfo); }
public override void CheckSemantic(SymbolTable symbolTable, List <CompileError> errors) { ///check semantics al VarDeclarationNode base.CheckSemantic(symbolTable, errors); ///check semantics al InitExpression InitExpression.CheckSemantic(symbolTable, errors); ///si InitExpression evalúa de error este también if (Object.Equals(InitExpression.NodeInfo, SemanticInfo.SemanticError)) { ///el nodo evalúa de error NodeInfo = SemanticInfo.SemanticError; return; } ///si InitExpression tiene tipo 'nil' if (InitExpression.NodeInfo.BuiltInType == BuiltInType.Nil) { errors.Add(new CompileError { Line = InitExpression.Line, Column = InitExpression.CharPositionInLine, ErrorMessage = "Cannot assign nil to an implicitly-typed local variable", Kind = ErrorKind.Semantic }); ///el nodo evalúa de error NodeInfo = SemanticInfo.SemanticError; } ///si no hubo error seteamos los campos necesarios if (!Object.Equals(NodeInfo, SemanticInfo.SemanticError)) { NodeInfo.Type = SemanticInfo.Void; NodeInfo.BuiltInType = BuiltInType.Void; } SemanticInfo variable = new SemanticInfo { Name = VariableName, ElementKind = SymbolKind.Variable, BuiltInType = InitExpression.NodeInfo.BuiltInType, ElementsType = InitExpression.NodeInfo.ElementsType, Fields = InitExpression.NodeInfo.Fields, Type = InitExpression.NodeInfo.Type.Type, ILType = InitExpression.NodeInfo.ILType }; ///seteamos el ILType del NodeInfo NodeInfo.ILType = InitExpression.NodeInfo.ILType; inferredParche = InitExpression.NodeInfo.Type; ///agregamos la variable a la tabla de símbolos symbolTable.InsertSymbol(variable); }
/// <summary> /// Gets the semantic types (and prefix mappings) for a given Model Type. /// </summary> /// <param name="modelType">The Model Type.</param> /// <param name="prefixMappings">The prefix mappings for the prefixes used by the types.</param> /// <returns>The semantic types.</returns> public static string[] GetSemanticTypes(Type modelType, out IDictionary <string, string> prefixMappings) { // No Tracer here to reduce trace noise. SemanticInfo semanticInfo = GetSemanticInfo(modelType); prefixMappings = semanticInfo.PrefixMappings; return(semanticInfo.PublicSemanticTypes.ToArray()); }
public override void CheckSemantic(SymbolTable symbolTable, List <CompileError> errors) { ///un type no puede ser alias de si mismo if (AliasId.Equals(OriginalId)) { errors.Add(new CompileError { Line = this.Line, Column = this.CharPositionInLine, ErrorMessage = "Defining a self recursive 'alias' type is not allowed", Kind = ErrorKind.Semantic }); ///el nodo evalúa de error NodeInfo = SemanticInfo.SemanticError; } SemanticInfo typeInfo; ///el tipo del que se es alias debe existir if (!symbolTable.GetDefinedTypeDeep(OriginalId, out typeInfo)) { errors.Add(new CompileError { Line = GetChild(1).Line, Column = GetChild(1).CharPositionInLine, ErrorMessage = string.Format("Type '{0}' could not be found in current context", OriginalId), Kind = ErrorKind.Semantic }); ///el nodo evalúa de error NodeInfo = SemanticInfo.SemanticError; } ///si no ha evaluado de error le seteamos los valores if (!Object.Equals(NodeInfo, SemanticInfo.SemanticError)) { NodeInfo.Type = SemanticInfo.Void; NodeInfo.BuiltInType = BuiltInType.Void; } SemanticInfo alias; symbolTable.GetDefinedTypeDeep(AliasId, out alias); alias.BuiltInType = typeInfo.BuiltInType; alias.ElementsType = typeInfo.ElementsType; alias.Fields = typeInfo.Fields; alias.Type = typeInfo.Type; alias.ILType = typeInfo.ILType; alias.IsPending = false; //change NodeInfo = SemanticInfo.Void; //me parece que el nodeinfo del aliasDeclaration tiene que ser void aliasParche = typeInfo; }
private string pop(out int val) { val = 0; if (mSemanticStack.Count == 0) { return("null_stack_!!!"); } SemanticInfo info = mSemanticStack.Pop(); val = info.value; return(info.token); }
public override void CheckSemantic(SymbolTable symbolTable, List <CompileError> errors) { ///check semantics al CallableDeclarationNode base.CheckSemantic(symbolTable, errors); ///si BodyExpression no evaluó de error if (!Object.Equals(CallableBody.NodeInfo, SemanticInfo.SemanticError)) { ///el procedimiento debe retornar void if (!CallableBody.NodeInfo.BuiltInType.IsCompatibleWith(BuiltInType.Void)) { errors.Add(new CompileError { Line = CallableBody.Line, Column = CallableBody.CharPositionInLine, ErrorMessage = string.Format("Cannot implicitly convert type '{0}' to 'void'", CallableBody.NodeInfo.Type.Name), Kind = ErrorKind.Semantic }); ///el nodo evalúa de error NodeInfo = SemanticInfo.SemanticError; } } ///si no ha evaluado de error le seteamos los valores if (!Object.Equals(NodeInfo, SemanticInfo.SemanticError)) { NodeInfo = new SemanticInfo { Name = SemanticInfo.NoName, ElementKind = SymbolKind.NoSymbol, Type = SemanticInfo.Void, BuiltInType = BuiltInType.Void, ILType = null }; SemanticInfo arg; ///guardamos los ILType for (int i = 0; i < Parameters.Count; i++) { symbolTable.GetDefinedTypeDeep(Parameters[i].Value, out arg); ILTypes.Add(arg.Type.ILType); } } SemanticInfo procedure; ///completamos la definición del procedimiento symbolTable.GetDefinedCallableDeep(CallableId, out procedure); procedure.IsPending = false; }
/// <summary> /// Gets the semantic property names for a given Model Type and property name. /// </summary> /// <param name="modelType">The Model Type.</param> /// <param name="propertyName">The property name.</param> /// <returns>The semantic property names or <c>null</c> if no semantic property names have been registered for the given property.</returns> public static string[] GetSemanticPropertyNames(Type modelType, string propertyName) { // No Tracer here to reduce trace noise. SemanticInfo semanticInfo = GetSemanticInfo(modelType); IList <string> semanticPropertyNames; if (semanticInfo.SemanticProperties.TryGetValue(propertyName, out semanticPropertyNames)) { return(semanticPropertyNames.ToArray()); } return(null); }
public override void CheckSemantic(SymbolTable symbolTable, List <CompileError> errors) { SemanticInfo variableInfo; ///chequeamos que no haya una variable con el mismo nombre if (symbolTable.GetDefinedVariableShallow(CallableId, out variableInfo)) { errors.Add(new CompileError { Line = GetChild(ChildCount - 2).Line, Column = GetChild(ChildCount - 2).CharPositionInLine, ErrorMessage = string.Format("There is already a definition for '{0}' in current context", CallableId), Kind = ErrorKind.Semantic }); ///el nodo evalúa de error NodeInfo = SemanticInfo.SemanticError; } ///creamos el scope de la función o procedimiento symbolTable.InitNewScope(); SemanticInfo param; ///agregamos los parámetros de la función o procedimiento al scope for (int i = 0; i < Parameters.Count; i++) { param = new SemanticInfo { Name = Parameters[i].Key, ElementKind = SymbolKind.Variable, BuiltInType = parametersType[i].BuiltInType, Type = parametersType[i], ElementsType = parametersType[i].ElementsType, Fields = parametersType[i].Fields }; symbolTable.InsertSymbol(param); } ///check semantics al CallableBody CallableBody.CheckSemantic(symbolTable, errors); ///destruimos el scope de la función o procedimiento symbolTable.CloseCurrentScope(); }
private static SemanticInfo RegisterModelType(Type modelType) { using (new Tracer(modelType)) { SemanticInfo semanticInfo = ExtractSemanticInfo(modelType); _modelTypeToSemanticInfoMapping.Add(modelType, semanticInfo); foreach (string semanticTypeName in semanticInfo.MappedSemanticTypes) { ISet <Type> mappedModelTypes; if (!_semanticTypeToModelTypesMapping.TryGetValue(semanticTypeName, out mappedModelTypes)) { mappedModelTypes = new HashSet <Type>(); _semanticTypeToModelTypesMapping.Add(semanticTypeName, mappedModelTypes); } mappedModelTypes.Add(modelType); int entityNameSeparatorPos = semanticTypeName.LastIndexOf(':'); string vocabularyId = semanticTypeName.Substring(0, entityNameSeparatorPos); string entityName = semanticTypeName.Substring(entityNameSeparatorPos + 1); IList <Tuple <string, Type> > entityNameModelTypeTuples; if (!_vocabularyToModelTypesMapping.TryGetValue(vocabularyId, out entityNameModelTypeTuples)) { entityNameModelTypeTuples = new List <Tuple <string, Type> >(); _vocabularyToModelTypesMapping.Add(vocabularyId, entityNameModelTypeTuples); } entityNameModelTypeTuples.Add(new Tuple <string, Type>(entityName, modelType)); } if (Log.IsDebugEnabled) { if (semanticInfo.PublicSemanticTypes.Any()) { Log.Debug("Model type '{0}' has semantic type(s) '{1}'.", modelType.FullName, String.Join(" ", semanticInfo.PublicSemanticTypes)); foreach (KeyValuePair <string, IList <string> > kvp in semanticInfo.SemanticProperties) { Log.Debug("\tRegistered property '{0}' as semantic property '{1}'", kvp.Key, String.Join(" ", kvp.Value)); } } } return(semanticInfo); } }
public override void CheckSemantic(SymbolTable symbolTable, List <CompileError> errors) { ///seteamos los campos necesarios NodeInfo = new SemanticInfo { BuiltInType = BuiltInType.Void, Type = SemanticInfo.Void }; ExpressionNode currentExpression = null; //check semantics a cada una de las expresiones for (int i = 0; i < ExpressionCount; i++) { currentExpression = ExpressionAt(i); ///check semantics a la currentExpression currentExpression.CheckSemantic(symbolTable, errors); ///si alguna de las expresiones evalúa de error este también if (Object.Equals(currentExpression.NodeInfo, SemanticInfo.SemanticError)) { ///el nodo evalúa de error NodeInfo = SemanticInfo.SemanticError; } } ///si este no ha evaluado de error if (!Object.Equals(NodeInfo, SemanticInfo.SemanticError)) { ///si hay mas de una expresión y ninguna tiene break if (ExpressionCount > 0 && !AnyExpressionContainsBreak) { //NodeInfo.BuiltInType = currentExpression.NodeInfo.BuiltInType; //NodeInfo.Type = currentExpression.NodeInfo.Type; //NodeInfo.ElementsType = currentExpression.NodeInfo.ElementsType; //NodeInfo.Fields = currentExpression.NodeInfo.Fields; //NodeInfo.ILType = currentExpression.NodeInfo.ILType; NodeInfo = currentExpression.NodeInfo; } } }
// <statblock> ::= { <statementstar> } | <statement> | e protected bool NTF_StatBlock(int p, SemanticInfo si) { bool error = SkipErrors(p, Lexer.Token.TokenType.OpenBrace, "if", "for", "cin", "cout", "return", Lexer.Token.TokenType.Identifier, "else", "fi", Lexer.Token.TokenType.Semicolon); if (lookahead.Type == Lexer.Token.TokenType.OpenBrace) { error |= !Match(p, Lexer.Token.TokenType.OpenBrace); error |= !NTF_StatementStar(p, si); error |= !Match(p, Lexer.Token.TokenType.CloseBrace); if (!error && p == 1) Log(LogType.Parse, "<statblock> ::= { <statementstar> }"); } // first(<statementstar>) else if (lookahead.Value == "if" || lookahead.Value == "for" || lookahead.Value == "cin" || lookahead.Value == "cout" || lookahead.Value == "return" || lookahead.Type == Lexer.Token.TokenType.Identifier) { error |= !NTF_Statement(p, si); if (!error && p == 1) Log(LogType.Parse, "<statblock> ::= <statement>"); } // follow(<statblock>)=else+fi+; else if (lookahead.Value == "else" || lookahead.Value == "fi" || lookahead.Type == Lexer.Token.TokenType.Semicolon) { if (p == 1) Log(LogType.Parse, "<statblock> ::= e"); } else error = true; return !error; }
private void _createFromOldFormat(XElement elementXML) { Debug.Assert(elementXML.Attribute(Consts.AttWordId) != null); Id = elementXML.Attribute(Consts.AttWordId).Value; // TODO: определить ElementType // ChildTreeInit // вершиной дерева всегда будет ID слова ChildWordsIds.AddChild(Id); // Order var orderNodeName = XName.Get(Consts.NodeWordOrder); Debug.Assert(elementXML.Element(orderNodeName) != null); Order = int.Parse(elementXML.Element(orderNodeName).Value); // Position - only in LWS var positionNodeName = XName.Get(Consts.NodeWordPosition); if (elementXML.Element(positionNodeName) != null) Position = int.Parse(elementXML.Element(Consts.NodeWordPosition).Value); else Position = -1; // Text var textNodeName = XName.Get(Consts.NodeWordText); if (elementXML.Element(textNodeName) != null) Text = elementXML.Element(textNodeName).Value; else Text = ""; // Syntactic Role var syntacticRoleNodeName = XName.Get(Consts.NodeSyntacticRole); if (elementXML.Element(syntacticRoleNodeName) != null) SyntacticRole = SyntacticRole.ReadFromString(elementXML.Element(syntacticRoleNodeName).Value); else SyntacticRole = SyntacticRole.Undefined; // Surface slot if (elementXML.Element(Consts.NodeSurfaceSlot) != null) SurfaceSlot = SurfaceSlot.ReadFromString(elementXML.Element(Consts.NodeSurfaceSlot).Value); else SurfaceSlot = SurfaceSlot.Undefined; // grammar info if (elementXML.Element(Consts.NodeGrammarInfo) != null) GrammarInfo = new GrammarInfo(elementXML.Element(Consts.NodeGrammarInfo)); else { GrammarInfo = new GrammarInfo(); GrammarInfo.Case = GrammarInfoCase.Undefined; GrammarInfo.PartOfSpeech = GrammarInfoPartOfSpeech.Undefined; } // is restored if (elementXML.Element(Consts.NodeIsRestored) != null) { if (elementXML.Element(Consts.NodeIsRestored).Value == Consts.ValueTrue) IsRestored = true; else IsRestored = false; } else IsRestored = false; //is word IsWord = elementXML.Attribute("type").Value == "Word"; // syntactic parent id if (elementXML.Element(Consts.NodeSyntacticParent) != null) SyntacticParentWordId = elementXML.Element(Consts.NodeSyntacticParent).Attribute(Consts.AttWithWordId).Value; else SyntacticParentWordId = "-1"; // controller nodes if (elementXML.Element(Consts.NodeHasController) != null) { foreach (var controllerItemXML in elementXML.Elements(Consts.NodeHasController)) ControllerNodes.Add(new Controller(controllerItemXML)); } // conjucted with if (elementXML.Element(Consts.NodeConjuctedWith) != null) ConjuctedWithId = elementXML.Element(Consts.NodeConjuctedWith).Attribute(Consts.AttWithWordId).Value; else ConjuctedWithId = "-1"; // semantic info SemanticInfo = new SemanticInfo(elementXML.Element(Consts.NodeSemanticInfo)); }
private static SemanticInfo ExtractSemanticInfo(Type modelType) { SemanticInfo semanticInfo = new SemanticInfo(); // Get model type name string modelTypeName = modelType.BareTypeName(); // Built-in semantic type mapping semanticInfo.MappedSemanticTypes.Add(SemanticMapping.GetQualifiedTypeName(modelTypeName)); // Extract semantic info from SemanticEntity attributes on the Model Type. foreach (SemanticEntityAttribute attribute in modelType.GetCustomAttributes <SemanticEntityAttribute>(inherit: true)) { semanticInfo.MappedSemanticTypes.Add(SemanticMapping.GetQualifiedTypeName(attribute.EntityName, attribute.Vocab)); string prefix = attribute.Prefix ?? string.Empty; if (attribute.Public && !String.IsNullOrEmpty(attribute.Prefix)) { string registeredVocab; if (semanticInfo.PrefixMappings.TryGetValue(prefix, out registeredVocab)) { // Prefix mapping already exists; must match. if (attribute.Vocab != registeredVocab) { throw new DxaException( String.Format("Attempt to use semantic prefix '{0}' for vocabulary '{1}', but is is already used for vocabulary '{2}", prefix, attribute.Vocab, registeredVocab) ); } } else { semanticInfo.PrefixMappings.Add(prefix, attribute.Vocab); } semanticInfo.PublicSemanticTypes.Add(String.Format("{0}:{1}", prefix, attribute.EntityName)); } // There may be multiple Semantic Entity attributes for the same prefix. The first one will be used. if (semanticInfo.PrefixToSemanticTypeMap.ContainsKey(prefix)) { if (Log.IsDebugEnabled) { Log.Debug($"Type '{modelType.FullName}' has multiple SemanticEntity attributes for prefix '{prefix}'. Ignoring '{attribute.EntityName}'."); } } else { semanticInfo.PrefixToSemanticTypeMap.Add(prefix, new SemanticType(attribute.EntityName, attribute.Vocab)); } } if (!semanticInfo.PrefixToSemanticTypeMap.ContainsKey(string.Empty)) { // If there is no SemanticEntity attribute without prefix, we add an implicit one: semanticInfo.PrefixToSemanticTypeMap.Add(string.Empty, new SemanticType(modelTypeName, SemanticMapping.DefaultVocabulary)); } string defaultPrefix; bool mapAllProperties; SemanticDefaultsAttribute semanticDefaultsAttr = modelType.GetCustomAttribute <SemanticDefaultsAttribute>(); if (semanticDefaultsAttr == null) { defaultPrefix = string.Empty; mapAllProperties = true; } else { defaultPrefix = semanticDefaultsAttr.Prefix; mapAllProperties = semanticDefaultsAttr.MapAllProperties; } foreach (PropertyInfo propertyInfo in modelType.GetProperties()) { // Extract semantic info from SemanticEntity attributes on the Model Type's properties bool useImplicitMapping = mapAllProperties; List <SemanticPropertyAttribute> attributes = propertyInfo.GetCustomAttributes <SemanticPropertyAttribute>(inherit: true).ToList(); // check if we should be ignoring this mapping completely if (attributes.Where(x => x.IgnoreMapping).Select(x => x).FirstOrDefault() != null) { continue; } List <SemanticProperty> semanticProperties = new List <SemanticProperty>(); foreach (SemanticPropertyAttribute attribute in attributes) { if (string.IsNullOrEmpty(attribute.PropertyName)) { continue; } // check for known property names switch (attribute.PropertyName) { // To do : we need to make this more generic to collect all fields of a given type (e.g. [SemtanticProperty("_all", typeof(Keyword)]) case SemanticProperty.AllFields: if (!typeof(IDictionary <string, string>).IsAssignableFrom(propertyInfo.PropertyType) && !typeof(IDictionary <string, KeywordModel>).IsAssignableFrom(propertyInfo.PropertyType)) { throw new DxaException( $"Invalid semantics for property {modelType.Name}.{propertyInfo.Name}. Properties with [SemanticProperty(\"_all\")] annotation must be of type Dictionary<string, string> or Dictionary<string, KeywordModel>." ); } break; case SemanticProperty.Self: Type elementType = GetElementType(propertyInfo.PropertyType); if (!typeof(MediaItem).IsAssignableFrom(elementType) && !typeof(Link).IsAssignableFrom(elementType) && (elementType != typeof(string)) && (elementType != typeof(RichText))) { throw new DxaException( $"Invalid semantics for property {modelType.Name}.{propertyInfo.Name}. Properties with [SemanticProperty(\"_self\")] annotation must be of type MediaItem, Link, String or RichText."); } break; } string prefix = attribute.Prefix; string name = attribute.PropertyName; if (prefix != null) { if (semanticInfo.PrefixMappings.ContainsKey(prefix)) { IList <string> semanticPropertyNames; if (!semanticInfo.SemanticProperties.TryGetValue(propertyInfo.Name, out semanticPropertyNames)) { semanticPropertyNames = new List <string>(); semanticInfo.SemanticProperties.Add(propertyInfo.Name, semanticPropertyNames); } semanticPropertyNames.Add(attribute.PropertyName); } } else { // Skip property names without prefix. prefix = defaultPrefix; useImplicitMapping = false; } SemanticType semanticType; if (!semanticInfo.PrefixToSemanticTypeMap.TryGetValue(prefix, out semanticType)) { throw new DxaException($"Use of undeclared prefix '{prefix}' in property '{propertyInfo.Name}' in type '{modelType.FullName}'."); } semanticProperties.Add(new SemanticProperty(prefix, name, semanticType)); } if (useImplicitMapping) { SemanticType semanticType; if (!semanticInfo.PrefixToSemanticTypeMap.TryGetValue(defaultPrefix, out semanticType)) { throw new DxaException($"Use of undeclared prefix '{defaultPrefix}' in property '{propertyInfo.Name}' in type '{modelType.FullName}'."); } SemanticProperty implicitSemanticProperty = new SemanticProperty( String.Empty, GetDefaultSemanticPropertyName(propertyInfo), semanticType ); semanticProperties.Add(implicitSemanticProperty); } if (semanticProperties.Count > 0) { if (semanticInfo.PropertySemantics.ContainsKey(propertyInfo.Name)) { // Properties with same name can exist is a property is reintroduced with a different signature in a subclass. if (Log.IsDebugEnabled) { Log.Debug("Property with name '{0}' is declared multiple times in type {1}.", propertyInfo.Name, modelType.FullName); } } else { semanticInfo.PropertySemantics.Add(propertyInfo.Name, semanticProperties); } } } return(semanticInfo); }
// <term> ::= <factor> <term2> protected bool NTF_Term(int p, SemanticInfo si) { bool error = SkipErrors(p, Lexer.Token.TokenType.Identifier, Lexer.Token.TokenType.OpenBracket, Lexer.Token.TokenType.Not, Lexer.Token.TokenType.Number, Lexer.Token.TokenType.Multiplicative, Lexer.Token.TokenType.Comma, Lexer.Token.TokenType.CloseBracket, Lexer.Token.TokenType.Comparison, Lexer.Token.TokenType.Additive, Lexer.Token.TokenType.Semicolon); error |= !NTF_Factor(p, si); error |= !NTF_Term2(p, si); if (!error && p == 1) Log(LogType.Parse, "<term> ::= <factor> <term2>"); return !error; }
public override void CheckSemantic(SymbolTable symbolTable, List <CompileError> errors) { SemanticInfo callableInfo; ///la función o procedimiento tiene que estar declarada(o) if (!symbolTable.GetDefinedCallableDeep(CallableId, out callableInfo)) { errors.Add(new CompileError { Line = Callable.Line, Column = Callable.CharPositionInLine, ErrorMessage = string.Format("The name '{0}' could not be found in current context", CallableId), Kind = ErrorKind.Semantic }); ///el nodo evalúa de error NodeInfo = SemanticInfo.SemanticError; return; } ///la cantidad de argumentos tiene que coincidir con los de su declaración if (callableInfo.Args.Count != ArgsCount) { errors.Add(new CompileError { Line = this.Line, Column = this.CharPositionInLine, ErrorMessage = string.Format("No overload for {0} '{1}' takes {2} arguments", (callableInfo.ElementKind == SymbolKind.Function) ? "function" : "procedure", CallableId, ArgsCount), Kind = ErrorKind.Semantic }); ///el nodo evalúa de error NodeInfo = SemanticInfo.SemanticError; return; } ExpressionNode currentArg; ///los tipos de los argumentos tienen que coincidir con los de su definición for (int i = 0; i < ArgsCount; i++) { ///obtenemos el i-ésimo argumento currentArg = ArgAt(i + 1); ///check semantics a currentArg currentArg.CheckSemantic(symbolTable, errors); ///si currentArg no evaluó de error if (!Object.Equals(currentArg.NodeInfo, SemanticInfo.SemanticError)) { ///si no coinciden los tipos if (!callableInfo.Args[i].Type.IsCompatibleWith(currentArg.NodeInfo.Type)) { errors.Add(new CompileError { Line = currentArg.Line, Column = currentArg.CharPositionInLine, ErrorMessage = string.Format("Argument {0}: cannot convert from '{1}' to '{2}'", i + 1, currentArg.NodeInfo.Type.Name, callableInfo.Args[i].Type.Name), Kind = ErrorKind.Semantic }); ///el nodo evalúa de error NodeInfo = SemanticInfo.SemanticError; } } else { ///hubo una argumento que evaluó de error ///el nodo evalúa de error NodeInfo = SemanticInfo.SemanticError; } } ///seteamos la información del NodeInfo if (!Object.Equals(NodeInfo, SemanticInfo.SemanticError)) { NodeInfo = new SemanticInfo { Name = SemanticInfo.NoName, ElementKind = SymbolKind.NoSymbol, BuiltInType = callableInfo.BuiltInType, Type = callableInfo.Type, ElementsType = callableInfo.ElementsType, Fields = callableInfo.Fields }; } }
public override void CheckSemantic(SymbolTable symbolTable, List <CompileError> errors) { SemanticInfo fieldInfo; for (int i = 0; i < FieldsCount; i++) { ///los tipos de los campos tienen que haber sido declarados if (!symbolTable.GetDefinedTypeDeep(Fields[i].Value, out fieldInfo)) { errors.Add(new CompileError { Line = GetChild(2 * i + 2).Line, Column = GetChild(2 * i + 2).CharPositionInLine, ErrorMessage = string.Format("Type '{0}' could not be found in current context", Fields[i].Value), Kind = ErrorKind.Semantic }); ///el nodo evalúa de error NodeInfo = SemanticInfo.SemanticError; } else { realFields.Add(fieldInfo); } for (int j = 0; j < i; j++) { ///chequeamos que no existan 2 campos con el mismo nombre if (Fields[i].Key.Equals(Fields[j].Key)) { errors.Add(new CompileError { Line = GetChild(2 * i + 1).Line, Column = GetChild(2 * i + 1).CharPositionInLine, ErrorMessage = string.Format("The field name '{0}' is a duplicate", Fields[i].Key), Kind = ErrorKind.Semantic }); ///el nodo evalúa de error NodeInfo = SemanticInfo.SemanticError; } } } /////si no ha evaluado de error le seteamos los valores //if (!Object.Equals(NodeInfo, SemanticInfo.SemanticError)) //{ // NodeInfo.Type = SemanticInfo.Void; // NodeInfo.BuiltInType = BuiltInType.Void; //} ///si evaluó de error if (Object.Equals(NodeInfo, SemanticInfo.SemanticError)) { ///no declaramos el record porque uno de sus campos no existe return; } ///seteamos la información del NodeInfo NodeInfo.Type = SemanticInfo.Void; NodeInfo.BuiltInType = BuiltInType.Void; List <KeyValuePair <string, SemanticInfo> > fields = new List <KeyValuePair <string, SemanticInfo> >(); ///guardamos los fields del record for (int i = 0; i < FieldsCount; i++) { fields.Add(new KeyValuePair <string, SemanticInfo>(Fields[i].Key, realFields[i])); } SemanticInfo recordAlias; symbolTable.GetDefinedTypeDeep(RecordId, out recordAlias); recordAlias.BuiltInType = BuiltInType.Record; recordAlias.Fields = fields; recordAlias.IsPending = false; recordAlias.Type = recordAlias; recordParche = recordAlias; }
public override void CheckSemantic(SymbolTable symbolTable, List <CompileError> errors) { ///check semantics al VarDeclarationNode base.CheckSemantic(symbolTable, errors); ///check semantics al InitExpression InitExpression.CheckSemantic(symbolTable, errors); ///si InitExpression evalúa de error este también if (Object.Equals(InitExpression.NodeInfo, SemanticInfo.SemanticError)) { ///el nodo evalúa de error NodeInfo = SemanticInfo.SemanticError; return; } SemanticInfo typeInfo; ///el tipo de la variable tiene que estar definido if (!symbolTable.GetDefinedTypeDeep(VarTypeId, out typeInfo)) { errors.Add(new CompileError { Line = VarType.Line, Column = VarType.CharPositionInLine, ErrorMessage = string.Format("Type '{0}' could not be found in current context", VarTypeId), Kind = ErrorKind.Semantic }); ///el nodo evalúa de error NodeInfo = SemanticInfo.SemanticError; } ///si existe el tipo de la variable if (!Object.Equals(typeInfo, SemanticInfo.SemanticError)) { ///el tipo de InitExpression y VarTypeId tienen que ser compatibles if (!InitExpression.NodeInfo.Type.IsCompatibleWith(typeInfo.Type)) { errors.Add(new CompileError { Line = VarType.Line, Column = VarType.CharPositionInLine, ErrorMessage = string.Format("Cannot implicitly convert type '{0}' to '{1}'", InitExpression.NodeInfo.Type.Name, VarTypeId), Kind = ErrorKind.Semantic }); ///el nodo evalúa de error NodeInfo = SemanticInfo.SemanticError; } } ///si no hubo error seteamos los campos necesarios if (!Object.Equals(NodeInfo, SemanticInfo.SemanticError)) { NodeInfo.Type = SemanticInfo.Void; NodeInfo.BuiltInType = BuiltInType.Void; } SemanticInfo variable = new SemanticInfo { Name = VariableName, ElementKind = SymbolKind.Variable, BuiltInType = typeInfo.BuiltInType, Type = typeInfo.Type, ElementsType = typeInfo.ElementsType, Fields = typeInfo.Fields }; ///guardamos el ILType en el NodeInfo NodeInfo.ILType = InitExpression.NodeInfo.ILType; ///agregamos la variable a la tabla de símbolos symbolTable.InsertSymbol(variable); }
// <array> ::= [ <int> ] | e protected bool NTF_Array(int p, SemanticInfo si) { bool error = SkipErrors(p, Lexer.Token.TokenType.OpenSquareBracket, Lexer.Token.TokenType.Comma, Lexer.Token.TokenType.CloseBracket, Lexer.Token.TokenType.Semicolon); if (lookahead.Type == Lexer.Token.TokenType.OpenSquareBracket) { SemanticInfo inti = new SemanticInfo(); error |= !Match(p, Lexer.Token.TokenType.OpenSquareBracket); error |= !NTF_Int(p, inti); error |= !Match(p, Lexer.Token.TokenType.CloseSquareBracket); si.ArrayIndices.Add(inti.Name); if (!error && p == 1) Log(LogType.Parse, "<array> ::= [ <int> ]"); } // follow=,+)+; else if (lookahead.Type == Lexer.Token.TokenType.Comma || lookahead.Type == Lexer.Token.TokenType.CloseBracket || lookahead.Type == Lexer.Token.TokenType.Semicolon) { if (p == 1) Log(LogType.Parse, "<array> ::= e"); } else error = true; return !error; }
// <arraystar> ::= e | <array> <arraystar> protected bool NTF_ArrayStar(int p, SemanticInfo si) { bool error = SkipErrors(p, Lexer.Token.TokenType.OpenSquareBracket, Lexer.Token.TokenType.Semicolon, Lexer.Token.TokenType.Comma, Lexer.Token.TokenType.CloseBracket); if (lookahead.Type == Lexer.Token.TokenType.OpenSquareBracket) { error |= !NTF_Array(p, si); error |= !NTF_ArrayStar(p, si); if (!error && p == 1) Log(LogType.Parse, "<arraystar> ::= <array> <arraystar>"); } // follow=;+,+) else if (lookahead.Type == Lexer.Token.TokenType.Semicolon || lookahead.Type == Lexer.Token.TokenType.Comma || lookahead.Type == Lexer.Token.TokenType.CloseBracket) { if (p == 1) Log(LogType.Parse, "<arraystar> ::= e"); } else error = true; return !error; }
// <arithexpr> ::= <term> <arithexpr2> | <sign> <term> <arithexpr2> protected bool NTF_ArithExpr(int p, SemanticInfo si) { bool error = SkipErrors(p, "+", "-", Lexer.Token.TokenType.Identifier, Lexer.Token.TokenType.Number, Lexer.Token.TokenType.OpenBracket, Lexer.Token.TokenType.Not, Lexer.Token.TokenType.Comparison, Lexer.Token.TokenType.Additive, Lexer.Token.TokenType.CloseSquareBracket, Lexer.Token.TokenType.Comma, Lexer.Token.TokenType.CloseBracket, Lexer.Token.TokenType.Semicolon); // first(<term>)=first(<variable>)+num+(+! if (lookahead.Type == Lexer.Token.TokenType.Identifier || lookahead.Type == Lexer.Token.TokenType.Number || lookahead.Type == Lexer.Token.TokenType.OpenBracket || lookahead.Type == Lexer.Token.TokenType.Not) { error |= !NTF_Term(p, si); error |= !NTF_ArithExpr2(p, si); if (!error && p == 1) Log(LogType.Parse, "<arithexpr> ::= <term> <arithexpr2>"); } else if (lookahead.Value == "+" || lookahead.Value == "-") { SemanticInfo si2 = new SemanticInfo(); error |= !NTF_Sign(p, si2); error |= !NTF_Term(p, si); si.Code.Append(si2.Code); error |= !NTF_ArithExpr2(p, si); if (!error && p == 1) Log(LogType.Parse, "<arithexpr> ::= <sign> <term> <arithexpr2>"); } else error = true; return !error; }
// <arithexpr2> ::= e | addop <term><arithexpr2> protected bool NTF_ArithExpr2(int p, SemanticInfo si) { bool error = SkipErrors(p, Lexer.Token.TokenType.Additive, Lexer.Token.TokenType.Semicolon, Lexer.Token.TokenType.CloseBracket, Lexer.Token.TokenType.Comparison, Lexer.Token.TokenType.CloseSquareBracket, Lexer.Token.TokenType.Comma); // first(<arithexpr2>)=addop if (lookahead.Type == Lexer.Token.TokenType.Additive) { string op = lookahead.Value; if (op == "+") op = "add"; else if (op == "-") op = "sub"; else if (op == "||") op = "or"; error |= !Match(p, Lexer.Token.TokenType.Additive); SemanticInfo si2 = new SemanticInfo(); error |= !NTF_Term(p, si2); if (p == 2) { if (si.Type == "int" && si2.Type == "int") { // TODO: handle logical or (and and) // paste si2 then add the 2 together freeing up the temp vars if needed si.Code.Append(si2.Code); si.Code.Append("addi r3,r14," + si.Offset + "\nlw r1,stack(r3)\n" + "addi r3,r14," + si2.Offset + "\nlw r2,stack(r3)\n" + op + " r1,r1,r2\n"); CompilerStack.Peek().SafeFreeTemp(si.Offset); CompilerStack.Peek().SafeFreeTemp(si2.Offset); int tmp = CompilerStack.Peek().RequestTemp() + CompilerStack.Peek().GetTotalRealOffset(); si.Code.Append("addi r2,r14," + tmp + "\nsw stack(r2),r1\n"); si.Offset = tmp; } } error |= !NTF_ArithExpr2(p, si); if (!error && p == 1) Log(LogType.Parse, "<arithexpr2> ::= addop <term> <arithexpr2>"); } // follow(<arithexpr2>)=follow(<arithexpr>)=follow(<expr>)+relop+addop+]+,+follow(<aparams>) // =;+)+relop+addop+]+, else if (lookahead.Type == Lexer.Token.TokenType.Semicolon || lookahead.Type == Lexer.Token.TokenType.CloseBracket || lookahead.Type == Lexer.Token.TokenType.Additive || lookahead.Type == Lexer.Token.TokenType.Comparison || lookahead.Type == Lexer.Token.TokenType.CloseSquareBracket || lookahead.Type == Lexer.Token.TokenType.Comma) { if (p == 1) Log(LogType.Parse, "<arithexpr2> ::= e"); } else error = true; return !error; }
// <aparamstailstar> ::= e | <aparamstail> <aparamstailstar> protected bool NTF_AParamsTailStar(int p, SemanticInfo si) { bool error = SkipErrors(p, Lexer.Token.TokenType.Comma, Lexer.Token.TokenType.CloseBracket); if (lookahead.Type == Lexer.Token.TokenType.Comma) { // TODO: handle function params error |= !NTF_AParamsTail(p, si); error |= !NTF_AParamsTailStar(p, si); if (!error && p == 1) Log(LogType.Parse, "<aparamstailstar> ::= <apramstail> <aparamstailstar>"); } // follow=) else if (lookahead.Type == Lexer.Token.TokenType.CloseBracket) { if (p == 1) Log(LogType.Parse, "<aparamstailstar> ::= e"); } else error = true; return !error; }
// <apramstail> ::= , <arithexpr> | e protected bool NTF_AParamsTail(int p, SemanticInfo si) { bool error = SkipErrors(p, Lexer.Token.TokenType.Comma, Lexer.Token.TokenType.CloseBracket); if (lookahead.Type == Lexer.Token.TokenType.Comma) { SemanticInfo si2 = new SemanticInfo(); error |= !Match(p, Lexer.Token.TokenType.Comma); error |= !NTF_ArithExpr(p, si2); if (p == 2) si.Parameters.Add(new SemanticInfo.ParameterInfo { Code = si2.Code, OldFrameOffset = si2.Offset, Type = si2.Type, }); if (!error && p == 1) Log(LogType.Parse, "<aparamstail> ::= , <arithexpr>"); } else if (lookahead.Type == Lexer.Token.TokenType.CloseBracket) { if (p == 1) Log(LogType.Parse, "<araparmstail> ::= e"); } else error = true; return !error; }
// <aparams> ::= <arithexpr> <aparamstailstar> | e protected bool NTF_AParams(int p, SemanticInfo si) { bool error = SkipErrors(p, "+", "-", Lexer.Token.TokenType.Identifier, Lexer.Token.TokenType.Number, Lexer.Token.TokenType.OpenBracket, Lexer.Token.TokenType.Not, Lexer.Token.TokenType.CloseBracket); // first(<arithexpr>)=++-+first(<term>)=++-+id+num+(+! if (lookahead.Value == "+" || lookahead.Value == "-" || lookahead.Type == Lexer.Token.TokenType.Identifier || lookahead.Type == Lexer.Token.TokenType.Number || lookahead.Type == Lexer.Token.TokenType.OpenBracket || lookahead.Type == Lexer.Token.TokenType.Not) { SemanticInfo si2 = new SemanticInfo(); error |= !NTF_ArithExpr(p, si2); if (p == 2) si.Parameters.Add(new SemanticInfo.ParameterInfo { Code = si2.Code, OldFrameOffset = si2.Offset, Type = si2.Type, }); error |= !NTF_AParamsTailStar(p, si2); if (!error && p == 1) Log(LogType.Parse, "<aparams> ::= <arithexpr> <aparamstail>"); } // follow = ) else if (lookahead.Type == Lexer.Token.TokenType.CloseBracket) { if (p == 1) Log(LogType.Parse, "<aparams> ::= e"); } else error = true; return !error; }
// <progbody> ::= program <funcbody>;<functionstar> // MODIFIED // <progbody> ::= program <funcbody>;<definitionstar> protected bool NTF_ProgBody(int p, SemanticInfo si) { bool error = SkipErrors(p, "program", Lexer.Token.TokenType.EndOfFile); if (p == 1) { SymbolTable.Information info; if ((info = CurrentScope.Find("$program", false)) != null) { SemanticErrorSymbolAlreadyDefined("$program"); error = true; if (info.Properties.ContainsKey("function_symtable")) if (info.Properties["function_symtable"] != null) CurrentScope = info.Properties["function_symtable"] as SymbolTable; else info.Properties["function_symtable"] = CurrentScope = CurrentScope.CreateChild("$program"); else { info.Properties.Add("function_symtable", CurrentScope.CreateChild("$program")); CurrentScope = info.Properties["function_symtable"] as SymbolTable; } } else { info = CurrentScope.Add("$program"); info.Kind = SymbolTable.Information.EKind.Function; info.Properties.Add("function_symtable", CurrentScope.CreateChild("$program")); info.Properties.Add("function_parameters", new List<SemanticInfo.ParameterInfo>()); info.Properties.Add("function_type", "<no type>"); CurrentScope = info.Properties["function_symtable"] as SymbolTable; } } else CurrentScope = CurrentScope.Find("$program", false).Properties["function_symtable"] as SymbolTable; if (p == 2) si.Code.Append("entry\n\nalign\naddi r14,r0,0\n"); error |= !Match(p, "program"); error |= !NTF_FuncBody(p, si); error |= !Match(p, Lexer.Token.TokenType.Semicolon); si.Code.Append("hlt\n"); CurrentScope = CurrentScope.Parent; error |= !NTF_DefinitionStar(p, si); if (!error && p == 1) Log(LogType.Parse, "<progbody> ::= program <funcbody> ; <definitionstar>"); return !error; }
// <classdecl> ::= class id { <typedeclstar> <functionstar> } ; // MODIFIED // <classdecl> ::= class id { <definitionstar> } ; protected bool NTF_ClassDecl(int p, SemanticInfo si) { /* if (Match("class") && Match(Lexer.Token.TokenType.Identifier) && Match(Lexer.Token.TokenType.OpenBrace) && NTF_TypeDeclStar() && NTF_FunctionStar() && Match(Lexer.Token.TokenType.CloseBrace) && Match(Lexer.Token.TokenType.Semicolon)) { Log("<classdecl> ::= class id {<typedeclstar><functionstar>};"); return true; } else return false; */ bool error = SkipErrors(p, "class", "program"); error |= !Match(p, "class"); if (p == 1) { SymbolTable child; SymbolTable.Information info; if ((info = CurrentScope.Find(lookahead.Value, false)) != null) { SemanticErrorSymbolAlreadyDefined(lookahead.Value); error = true; if (info.Properties.ContainsKey("class_symtable")) if (info.Properties["class_symtable"] != null) child = info.Properties["class_symtable"] as SymbolTable; else info.Properties["class_symtable"] = child = CurrentScope.CreateChild(lookahead.Value); else { info.Properties.Add("class_symtable", CurrentScope.CreateChild(lookahead.Value)); child = info.Properties["class_symtable"] as SymbolTable; } } else { info = CurrentScope.Add(lookahead.Value); child = CurrentScope.CreateChild(lookahead.Value); info.Kind = SymbolTable.Information.EKind.Class; info.Properties.Add("class_symtable", child); } CurrentScope = child; } else { CurrentScope = CurrentScope.Find(lookahead.Value, false).Properties["class_symtable"] as SymbolTable; } error |= !Match(p, Lexer.Token.TokenType.Identifier); error |= !Match(p, Lexer.Token.TokenType.OpenBrace); error |= !NTF_DefinitionStar(p, si); error |= !Match(p, Lexer.Token.TokenType.CloseBrace); error |= !Match(p, Lexer.Token.TokenType.Semicolon); CurrentScope = CurrentScope.Parent; if (!error && p == 1) Log(LogType.Parse, "<classdecl> := class id { <definitionstar> } ;"); return !error; }
private static SemanticInfo ExtractSemanticInfo(Type modelType) { SemanticInfo semanticInfo = new SemanticInfo(); // Built-in semantic type mapping string bareTypeName = modelType.Name.Split('`')[0]; // Type name without generic type parameters (if any) semanticInfo.MappedSemanticTypes.Add(SemanticMapping.GetQualifiedTypeName(bareTypeName)); // Extract semantic info from SemanticEntity attributes on the Model Type. foreach (SemanticEntityAttribute attribute in modelType.GetCustomAttributes(true).Where(a => a is SemanticEntityAttribute)) { semanticInfo.MappedSemanticTypes.Add(SemanticMapping.GetQualifiedTypeName(attribute.EntityName, attribute.Vocab)); if (!attribute.Public || string.IsNullOrEmpty(attribute.Prefix)) { continue; } string prefix = attribute.Prefix; string registeredVocab; if (semanticInfo.PrefixMappings.TryGetValue(prefix, out registeredVocab)) { // Prefix mapping already exists; must match. if (attribute.Vocab != registeredVocab) { throw new DxaException( string.Format("Attempt to use semantic prefix '{0}' for vocabulary '{1}', but is is already used for vocabulary '{2}", prefix, attribute.Vocab, registeredVocab) ); } } else { semanticInfo.PrefixMappings.Add(prefix, attribute.Vocab); } semanticInfo.PublicSemanticTypes.Add(String.Format("{0}:{1}", prefix, attribute.EntityName)); } // Extract semantic info from SemanticEntity attributes on the Model Type's properties foreach (MemberInfo memberInfo in modelType.GetMembers(BindingFlags.Public | BindingFlags.Instance)) { foreach (SemanticPropertyAttribute attribute in memberInfo.GetCustomAttributes(true).Where(a => a is SemanticPropertyAttribute)) { if (string.IsNullOrEmpty(attribute.PropertyName)) { // Skip properties without name. continue; } string[] semanticPropertyNameParts = attribute.PropertyName.Split(':'); if (semanticPropertyNameParts.Length < 2) { // Skip property names without prefix. continue; } string prefix = semanticPropertyNameParts[0]; if (!semanticInfo.PrefixMappings.ContainsKey(prefix)) { // Skip property names with prefix which is not declared as public prefix on the type. continue; } IList <string> semanticPropertyNames; if (!semanticInfo.SemanticProperties.TryGetValue(memberInfo.Name, out semanticPropertyNames)) { semanticPropertyNames = new List <string>(); semanticInfo.SemanticProperties.Add(memberInfo.Name, semanticPropertyNames); } semanticPropertyNames.Add(attribute.PropertyName); } } return(semanticInfo); }
// <classdeclstar> ::= e | <classdecl><classdeclstar> protected bool NTF_ClassDeclStar(int p, SemanticInfo si) { bool error = SkipErrors(p, "class", "program"); if (lookahead.Value == "class") // first(<classdecl>) { error |= !NTF_ClassDecl(p, si); error |= !NTF_ClassDeclStar(p, si); if (!error && p == 1) Log(LogType.Parse, "<classdeclstar> ::= <classdecl><classdeclstar>"); } else if (lookahead.Value == "program") // follow(<classdecl>) { if (p == 1) Log(LogType.Parse, "<classdeclstar> ::= e"); } else error = true; return !error; }
// <variable> ::= <idnest> <indicestar> protected bool NTF_Variable(int p, SemanticInfo si) { bool error = SkipErrors(p, Lexer.Token.TokenType.Identifier, Lexer.Token.TokenType.Assignement, Lexer.Token.TokenType.Multiplicative, Lexer.Token.TokenType.Additive, Lexer.Token.TokenType.Comparison, Lexer.Token.TokenType.Comma, Lexer.Token.TokenType.CloseBracket, Lexer.Token.TokenType.Semicolon); SemanticInfo si2 = new SemanticInfo(); error |= !NTF_IdNest(p, si2); error |= !NTF_IndiceStar(p, si2); if (p == 2) { // find the type of this variable SymbolTable st = CurrentScope; SymbolTable.Information info; si.Offset = 0; foreach (SemanticInfo.ParameterInfo pi in si2.Parameters) { info = st.Find(pi.Name, true); if (info == null || info.Kind != SymbolTable.Information.EKind.Variable) { SemanticErrorVariableNotFound(pi.Name); return false; } si.Offset += (int)info.Properties["variable_offset"]; info = Global.Find(info.Properties["variable_type"] as string, false); if (info == null || info.Kind != SymbolTable.Information.EKind.Class) { SemanticErrorWrongType(pi.Name); return false; } st = info.Properties["class_symtable"] as SymbolTable; } info = st.Find(si2.Name, si2.Parameters.Count == 0); if (info == null || info.Kind != SymbolTable.Information.EKind.Variable) { SemanticErrorVariableNotFound(si.Name); return false; } si.Type = (string)info.Properties["variable_type"]; si.Offset += (int)info.Properties["variable_offset"]; } if (!error && p == 1) Log(LogType.Parse, "<variable> ::= <idnest> <indicestar>"); return !error; }
// <definition> ::= <type> id <definition2> protected bool NTF_Definition(int p, SemanticInfo si) { bool error = SkipErrors(p, "int", "float", Lexer.Token.TokenType.Identifier, Lexer.Token.TokenType.CloseBrace, Lexer.Token.TokenType.EndOfFile); error |= !NTF_Type(p, si); si.Name = lookahead.Value; error |= !Match(p, Lexer.Token.TokenType.Identifier); error |= !NTF_Definition2(p, si); if (!error && p == 1) Log(LogType.Parse, "<definition> ::= <type> id <definition2>"); return !error; }
// <term2> ::= e | multop <factor> <term2> protected bool NTF_Term2(int p, SemanticInfo si) { bool error = SkipErrors(p, Lexer.Token.TokenType.Multiplicative, Lexer.Token.TokenType.Semicolon, Lexer.Token.TokenType.CloseBracket, Lexer.Token.TokenType.Additive, Lexer.Token.TokenType.Comparison, Lexer.Token.TokenType.CloseSquareBracket, Lexer.Token.TokenType.Comma); if (lookahead.Type == Lexer.Token.TokenType.Multiplicative) { string op = lookahead.Value; if (op == "*") op = "mul"; else if (op == "/") op = "div"; else if (op == "&&") op = "and"; error |= !Match(p, Lexer.Token.TokenType.Multiplicative); SemanticInfo si2 = new SemanticInfo(); error |= !NTF_Factor(p, si2); if (p == 2) { // TODO: handle more types if (si.Type == "int" && si2.Type == "int") { // TODO: handle logical or (and and) // paste si2 then add the 2 together freeing up the temp vars if needed si.Code.Append(si2.Code); si.Code.Append("addi r3,r14," + si.Offset + "\nlw r1,stack(r3)\n" + "addi r3,r14," + si2.Offset + "\nlw r2,stack(r3)\n" + op + " r1,r1,r2\n"); CompilerStack.Peek().SafeFreeTemp(si.Offset); CompilerStack.Peek().SafeFreeTemp(si2.Offset); int tmp = CompilerStack.Peek().RequestTemp() + CompilerStack.Peek().GetTotalRealOffset(); si.Code.Append("addi r2,r14," + tmp + "\nsw stack(r2),r1\n"); si.Offset = tmp; } else { if (si.Type != "int") SemanticErrorWrongType(si.Name); if (si2.Type != "int") SemanticErrorWrongType(si2.Name); error = true; } } error |= !NTF_Term2(p, si); if (!error && p == 1) Log(LogType.Parse, "<term2> ::= multop <factor> <term2>"); } // follow(<term2>)=follow(<term>)=follow(<arithexpr>)=;+)+relop+addop+]+, else if (lookahead.Type == Lexer.Token.TokenType.Semicolon || lookahead.Type == Lexer.Token.TokenType.CloseBracket || lookahead.Type == Lexer.Token.TokenType.Additive || lookahead.Type == Lexer.Token.TokenType.Comparison || lookahead.Type == Lexer.Token.TokenType.CloseSquareBracket || lookahead.Type == Lexer.Token.TokenType.Comma) { if (p == 1) Log(LogType.Parse, "<term2> ::= e"); } else error = true; return !error; }
// <definition2> ::= ( <fparams> ) <funcbody> ; // | <arraystar> ; protected bool NTF_Definition2(int p, SemanticInfo si) { bool error = SkipErrors(p, Lexer.Token.TokenType.OpenBracket, Lexer.Token.TokenType.OpenSquareBracket, Lexer.Token.TokenType.Semicolon, Lexer.Token.TokenType.CloseBrace, Lexer.Token.TokenType.EndOfFile); if (lookahead.Type == Lexer.Token.TokenType.OpenBracket) { error |= !Match(p, Lexer.Token.TokenType.OpenBracket); SemanticInfo si2 = new SemanticInfo(); error |= !NTF_FParams(p, si2); error |= !Match(p, Lexer.Token.TokenType.CloseBracket); if (p == 1) { SymbolTable.Information info; if ((info = CurrentScope.Find(si.Name, false)) != null) { SemanticErrorSymbolAlreadyDefined(si.Name); error = true; if (info.Properties.ContainsKey("function_symtable")) if (info.Properties["function_symtable"] != null) CurrentScope = info.Properties["function_symtable"] as SymbolTable; else info.Properties["function_symtable"] = CurrentScope = CurrentScope.CreateChild(si.Name); else { info.Properties.Add(si.Name, CurrentScope.CreateChild(si.Name)); CurrentScope = info.Properties[si.Name] as SymbolTable; } } else { info = CurrentScope.Add(si.Name); info.Kind = SymbolTable.Information.EKind.Function; info.Properties.Add("function_parameters", si2.Parameters); info.Properties.Add("function_type", si.Type); info.Properties.Add("function_symtable", CurrentScope.CreateChild(si.Name)); CurrentScope = info.Properties["function_symtable"] as SymbolTable; // also add the parameters as member variables foreach (SemanticInfo.ParameterInfo pi in si2.Parameters) { SymbolTable.Information inf = (info.Properties["function_symtable"] as SymbolTable) .Add(pi.Name); inf.Kind = SymbolTable.Information.EKind.Variable; inf.Properties.Add("variable_type", pi.Type); inf.Properties.Add("variable_arrayindices", pi.ArrayIndices.ToArray()); //inf.Properties.Add("variable_offset", CompilerStack.Peek().GetTotalRealOffset()); } } } else { si.Code.Append(si2.Code); CurrentScope = CurrentScope.Find(si.Name, false).Properties["function_symtable"] as SymbolTable; } CompilerStack.Push(new StackFrame(this, true)); // the function label if (p == 2) si.Code.Append(GetFunctionLabelName(CurrentScope.Parent, si.Name) + " nop\n"); error |= !NTF_FuncBody(p, si); error |= !Match(p, Lexer.Token.TokenType.Semicolon); if (p == 2) si.Code.Append("% append default return\naddi r1,r0,0\njr r15\n"); CompilerStack.Pop(); CurrentScope = CurrentScope.Parent; if (!error && p == 1) Log(LogType.Parse, "<definition2> ::= ( <fparams> ) <funcbody> ;"); } else if (lookahead.Type == Lexer.Token.TokenType.OpenSquareBracket || lookahead.Type == Lexer.Token.TokenType.Semicolon) { error |= !NTF_ArrayStar(p, si); error |= !Match(p, Lexer.Token.TokenType.Semicolon); if (p == 1) { SymbolTable.Information info; if ((info = CurrentScope.Find(si.Name, false)) != null) { SemanticErrorSymbolAlreadyDefined(si.Name); error = true; } else { info = CurrentScope.Add(si.Name); info.Kind = SymbolTable.Information.EKind.Variable; info.Properties["variable_arrayindices"] = new string[si.ArrayIndices.Count]; for (int i = 0; i < si.ArrayIndices.Count; ++i) (info.Properties["variable_arrayindices"] as string[])[i] = si.ArrayIndices[i]; info.Properties["variable_type"] = si.Type; // TODO: account for objects bigger than 4 //info.Properties.Add("variable_offset", CompilerStack.Peek().GetTotalRealOffset()); } } if (!error && p == 1) Log(LogType.Parse, "<definition2> ::= <arraystar> ;"); } return !error; }
// <statementstar> ::= e | <statement><statementstar> protected bool NTF_StatementStar(int p, SemanticInfo si) { bool error = SkipErrors(p, "if", "for", "cin", "cout", "return", Lexer.Token.TokenType.Identifier, Lexer.Token.TokenType.CloseBrace); // first(<statement>)=first(<variable>)+if+for+cin+cout+return // =first(<idnest>)+id+if+for+cin+cout+return // =id+if+for+cin+cout+return if (lookahead.Value == "if" || lookahead.Value == "for" || lookahead.Value == "cin" || lookahead.Value == "cout" || lookahead.Value == "return" || lookahead.Type == Lexer.Token.TokenType.Identifier) { error |= !NTF_Statement(p, si); error |= !NTF_StatementStar(p, si); if (!error && p == 1) Log(LogType.Parse, "<statementstar> ::= <statement><statementstar>"); } // follow(<statementstar>)=} else if (lookahead.Type == Lexer.Token.TokenType.CloseBrace) { if (p == 1) Log(LogType.Parse, "<statementstar> ::= e"); } else error = true; return !error; }
public override void CheckSemantic(SymbolTable symbolTable, List <CompileError> errors) { ///check semantics al CallableDeclarationNode base.CheckSemantic(symbolTable, errors); SemanticInfo returnTypeInfo; ///chequeamos si existe el tipo de retorno if (!symbolTable.GetDefinedTypeDeep(ReturnType, out returnTypeInfo)) { errors.Add(new CompileError { Line = GetChild(ChildCount - 2).Line, Column = GetChild(ChildCount - 2).CharPositionInLine, ErrorMessage = string.Format("Type '{0}' could not be found in current context", ReturnType), Kind = ErrorKind.Semantic }); ///el nodo evalúa de error NodeInfo = SemanticInfo.SemanticError; } ///si CallableBody no evaluó de error y se encontró el tipo de retorno if (!Object.Equals(CallableBody.NodeInfo, SemanticInfo.SemanticError) && !Object.Equals(returnTypeInfo, SemanticInfo.SemanticError)) { ///el tipo deretorno del CallableBody tiene que ser compatible con el tipo de retorno if (!CallableBody.NodeInfo.Type.IsCompatibleWith(returnTypeInfo)) { errors.Add(new CompileError { Line = GetChild(ChildCount - 2).Line, Column = GetChild(ChildCount - 2).CharPositionInLine, ErrorMessage = string.Format("Cannot implicitly convert type '{0}' to '{1}'", CallableBody.NodeInfo.Type.Name, returnTypeInfo.Type.Name), Kind = ErrorKind.Semantic }); ///el nodo evalúa de error NodeInfo = SemanticInfo.SemanticError; } } ///si no ha evaluado de error le seteamos los valores if (!Object.Equals(NodeInfo, SemanticInfo.SemanticError)) { NodeInfo = new SemanticInfo { Name = SemanticInfo.NoName, ElementKind = SymbolKind.NoSymbol, Type = SemanticInfo.Void, BuiltInType = BuiltInType.Void, ILType = returnTypeInfo.ILType }; functionParche = returnTypeInfo; SemanticInfo arg; ///guardamos los ILType for (int i = 0; i < Parameters.Count; i++) { symbolTable.GetDefinedTypeDeep(Parameters[i].Value, out arg); ILTypes.Add(arg.ILType); } } SemanticInfo function; ///completamos la definición de la función symbolTable.GetDefinedCallableDeep(CallableId, out function); function.IsPending = false; }
private void _createFromAPIFormat(XElement elementXML, bool useNamespaces) { // смотрим что обрабатываем - слово или знак препинания var elementNode = elementXML.Element(XName.Get(Consts.NodeWord, Namespaces.NamespaceLinguistic)); if (elementNode != null) ElementType = ComprenoSentenceElementType.ReadFromString(elementNode.Name.LocalName); else { elementNode = elementXML.Element(XName.Get(Consts.NodePunctuator, useNamespaces ? Namespaces.NamespaceLinguistic : "")); if (elementNode != null) ElementType = ComprenoSentenceElementType.ReadFromString(elementNode.Element(XName.Get(Consts.NodePunctuatorType, useNamespaces ? Namespaces.NamespaceLinguistic : "")).Attribute(XName.Get(Consts.AttResourse, useNamespaces ? Namespaces.NamespaceRDF : "")).Value); } Debug.Assert(elementNode != null); Id = elementNode.Attribute(XName.Get(Consts.AttElementNodeId, useNamespaces ? Namespaces.NamespaceRDF : "")).Value; // проваливаемся на 1 уровень ниже - на нем располагаются все свойства elementXML = elementNode; var nodeIdName = XName.Get(Consts.AttElementNodeId, useNamespaces ? Namespaces.NamespaceRDF : ""); // ChildTreeInit // вершиной дерева всегда будет ID слова ChildWordsIds.AddChild(Id); // Order var orderNodeName = XName.Get(Consts.NodeWordOrder, useNamespaces ? Namespaces.NamespaceLinguistic : ""); Debug.Assert(elementXML.Element(orderNodeName) != null); Order = int.Parse(elementXML.Element(orderNodeName).Value); // Text var textNodeName = XName.Get(Consts.NodeWordText, useNamespaces ? Namespaces.NamespaceLinguistic : ""); if (elementXML.Element(textNodeName) != null) Text = elementXML.Element(textNodeName).Value; else Text = ""; // Lemma var lemmaNodeName = XName.Get(Consts.NodeLemmaName, useNamespaces ? Namespaces.NamespaceLinguistic : ""); if (elementXML.Element(lemmaNodeName) != null) Lemma = elementXML.Element(lemmaNodeName).Value; else Lemma = ""; // Syntactic Role var syntacticRoleNodeName = XName.Get(Consts.NodeSyntacticRole, useNamespaces ? Namespaces.NamespaceLinguistic : ""); var syntacticRoleAttName = XName.Get(Consts.AttResourse, useNamespaces ? Namespaces.NamespaceRDF : ""); if (elementXML.Element(syntacticRoleNodeName) != null) SyntacticRole = SyntacticRole.ReadFromString(elementXML.Element(syntacticRoleNodeName).Attribute(syntacticRoleAttName).Value); else SyntacticRole = SyntacticRole.Undefined; // Surface slot var surfaceSlotNodeName = XName.Get(Consts.NodeSurfaceSlot, useNamespaces ? Namespaces.NamespaceLinguistic : ""); if (elementXML.Element(surfaceSlotNodeName) != null) SurfaceSlot = SurfaceSlot.ReadFromString(elementXML.Element(surfaceSlotNodeName).Value); else SurfaceSlot = SurfaceSlot.Undefined; // grammar info var grammarInfoNodeName = XName.Get(Consts.NodeGrammarInfo, useNamespaces ? Namespaces.NamespaceLinguistic : ""); if (elementXML.Element(grammarInfoNodeName) != null) GrammarInfo = new GrammarInfo(elementXML.Element(grammarInfoNodeName), useNamespaces); else GrammarInfo = new GrammarInfo(); // is restored var isRestoredNodeName = XName.Get(Consts.NodeIsRestored, useNamespaces ? Namespaces.NamespaceLinguistic : ""); if (elementXML.Element(isRestoredNodeName) != null) IsRestored = (elementXML.Element(isRestoredNodeName).Value == Consts.ValueTrue); else IsRestored = false; //is word IsWord = ComprenoSentenceElementType.IsWord(ElementType); // syntactic parent id var syntacticParentNodeName = XName.Get(Consts.NodeSyntacticParent, useNamespaces ? Namespaces.NamespaceLinguistic : ""); if (elementXML.Element(syntacticParentNodeName) != null) SyntacticParentWordId = elementXML.Element(syntacticParentNodeName).Attribute(nodeIdName).Value; else SyntacticParentWordId = "-1"; // controller nodes var controllerNodeName = XName.Get(Consts.NodeHasController, useNamespaces ? Namespaces.NamespaceLinguistic : ""); if (elementXML.Element(controllerNodeName) != null) { var singleControllerNodeName = XName.Get(Consts.NodeController, useNamespaces ? Namespaces.NamespaceLinguistic : ""); foreach (var controllerItemXML in elementXML.Element(controllerNodeName).Elements(singleControllerNodeName)) ControllerNodes.Add(new Controller(controllerItemXML, useNamespaces)); } // conjucted with var conjuctedWithNodeName = XName.Get(Consts.NodeConjuctedWith, useNamespaces ? Namespaces.NamespaceLinguistic : ""); if (elementXML.Element(conjuctedWithNodeName) != null) ConjuctedWithId = elementXML.Element(conjuctedWithNodeName).Attribute(nodeIdName).Value; else ConjuctedWithId = "-1"; // semantic info --> lexical class predefined var semanticInfoNodeName = XName.Get(Consts.NodeSemanticInfo, useNamespaces ? Namespaces.NamespaceLinguistic : ""); SemanticInfo = new SemanticInfo(elementXML.Element(semanticInfoNodeName), useNamespaces); }
// <expr> ::= <arithexpr><expr2> protected bool NTF_Expr(int p, SemanticInfo si) { bool error = SkipErrors(p, "+", "-", Lexer.Token.TokenType.Identifier, Lexer.Token.TokenType.Number, Lexer.Token.TokenType.OpenBracket, Lexer.Token.TokenType.Not, Lexer.Token.TokenType.Semicolon, Lexer.Token.TokenType.CloseBracket); error |= !NTF_ArithExpr(p, si); error |= !NTF_Expr2(p, si); if (!error && p == 1) Log(LogType.Parse, "<expr> ::= <arithexpr> <expr2>"); return !error; }
// <statement> ::= <variable> := <expr> // | if ( <expr> ) then <statblock> else <statblock> fi ; // | for ( <statement> ; <expr> ; <statement> ) <statblock> ; // | cin ( <variable> ) ; // | cout ( <expr> ) ; // | return ( <expr> ) ; protected bool NTF_Statement(int p, SemanticInfo si) { bool error = SkipErrors(p, Lexer.Token.TokenType.Identifier, "if", "for", "cin", "cout", "return", Lexer.Token.TokenType.CloseBrace, Lexer.Token.TokenType.Semicolon, "else", "fi"); SemanticInfo si2, si3, si4, si5; // first(<variable>) if (lookahead.Type == Lexer.Token.TokenType.Identifier) { si2 = new SemanticInfo(); error |= !NTF_Variable(p, si2); error |= !Match(p, Lexer.Token.TokenType.Assignement); si3 = new SemanticInfo(); error |= !NTF_Expr(p, si3); error |= !Match(p, Lexer.Token.TokenType.Semicolon); if (p == 2) { // check to see if the types match if (si2.Type != si3.Type) SemanticErrorWrongTypeExpected(si3.Type, si2.Type); // paste si3.code and store the offset, after which you free the temp var if necessary si.Code.Append(si3.Code); si.Code.Append("addi r1,r14," + si3.Offset + "\nlw r2,stack(r1)\naddi r1,r14," + si2.Offset + "\nsw stack(r1), r2\n"); } if (!error && p == 1) Log(LogType.Parse, "<statement> ::= <variable> := <expr>"); } else if (lookahead.Value == "if") { error |= !Match(p, "if"); error |= !Match(p, Lexer.Token.TokenType.OpenBracket); si2 = new SemanticInfo(); error |= !NTF_Expr(p, si2); error |= !Match(p, Lexer.Token.TokenType.CloseBracket); error |= !Match(p, "then"); si3 = new SemanticInfo(); error |= !NTF_StatBlock(p, si3); error |= !Match(p, "else"); si4 = new SemanticInfo(); error |= !NTF_StatBlock(p, si4); error |= !Match(p, "fi"); error |= !Match(p, Lexer.Token.TokenType.Semicolon); if (p == 2) { // test expression si.Code.Append(si2.Code); // jump string j1 = GetNewJumpLabel(); si.Code.Append("addi r2,r14," + si2.Offset + "\nlw r1,stack(r2)\nbz r1, " + j1 + "\n"); // then code si.Code.Append(si3.Code); // exit if string j2 = GetNewJumpLabel(); si.Code.Append("j " + j2 + "\n"); // else code si.Code.Append(j1 + " nop\n"); si.Code.Append(si4.Code); // finish up si.Code.Append(j2 + " nop\n"); } if (!error && p == 1) Log(LogType.Parse, "<statement> ::= if ( <expr> ) then <statblock> else <statblock> fi ;"); } else if (lookahead.Value == "for") { error |= !Match(p, "for"); error |= !Match(p, Lexer.Token.TokenType.OpenBracket); si2 = new SemanticInfo(); error |= !NTF_Statement(p, si2); error |= !Match(p, Lexer.Token.TokenType.Semicolon); si3 = new SemanticInfo(); error |= !NTF_Expr(p, si3); error |= !Match(p, Lexer.Token.TokenType.Semicolon); si4 = new SemanticInfo(); error |= !NTF_Statement(p, si4); error |= !Match(p, Lexer.Token.TokenType.CloseBracket); si5 = new SemanticInfo(); error |= !NTF_StatBlock(p, si5); error |= !Match(p, Lexer.Token.TokenType.Semicolon); if (p == 2) { // init si.Code.Append(si2.Code); // add the label string j1 = GetNewJumpLabel(); si.Code.AppendLine(j1 + " nop"); // test si.Code.Append(si3.Code); string j2 = GetNewJumpLabel(); si.Code.AppendLine("addi r2,r14," + si3.Offset + "\nlw r1,stack(r2)\nbz r1," + j2); // statements and increment si.Code.Append(si5.Code); si.Code.Append(si4.Code); // jump back to the test si.Code.AppendLine("j " + j1); // exit label si.Code.AppendLine(j2 + " nop"); } if (!error && p == 1) Log(LogType.Parse, "<statement> ::= for ( <statement> ; <expr> ; <statement> ) <statblock> ;"); } else if (lookahead.Value == "cin") { error |= !Match(p, "cin"); error |= !Match(p, Lexer.Token.TokenType.OpenBracket); si2 = new SemanticInfo(); error |= !NTF_Variable(p, si2); error |= !Match(p, Lexer.Token.TokenType.CloseBracket); error |= !Match(p, Lexer.Token.TokenType.Semicolon); if (p == 2) { int[] tmp = CompilerStack.Peek().GenerateBackupRegisters(si.Code); si.Code.Append("jl r15,getint\naddi r2,r14," + si2.Offset + "\nsw stack(r2),r1\n"); CompilerStack.Peek().GenerateRestoreRegisters(si.Code, tmp); } if (!error && p == 1) Log(LogType.Parse, "<statement> ::= cin ( <variable> ) ;"); } else if (lookahead.Value == "cout") { error |= !Match(p, "cout"); error |= !Match(p, Lexer.Token.TokenType.OpenBracket); si2 = new SemanticInfo(); error |= !NTF_Expr(p, si2); error |= !Match(p, Lexer.Token.TokenType.CloseBracket); error |= !Match(p, Lexer.Token.TokenType.Semicolon); if (p == 2) { // append si2 and load the temp register into r1 before calling cout si.Code.Append(si2.Code); int[] tmp = CompilerStack.Peek().GenerateBackupRegisters(si.Code); si.Code.Append("addi r2,r14," + si2.Offset + "\nlw r1,stack(r2)\n"); si.Code.Append("jl r15,putint\n"); CompilerStack.Peek().GenerateRestoreRegisters(si.Code, tmp); } if (!error && p == 1) Log(LogType.Parse, "<statement> ::= cout ( <expr> ) ;"); } else if (lookahead.Value == "return") { error |= !Match(p, "return"); error |= !Match(p, Lexer.Token.TokenType.OpenBracket); si2 = new SemanticInfo(); error |= !NTF_Expr(p, si2); error |= !Match(p, Lexer.Token.TokenType.CloseBracket); error |= !Match(p, Lexer.Token.TokenType.Semicolon); if (p == 2) { si.Code.Append(si2.Code); // store the return in r1 // make sure the return type matches SymbolTable.Information info = CurrentScope.Parent.Find(CurrentScope.ID, false); if (info.Properties["function_type"] as string != si2.Type) { error = true; SemanticErrorWrongReturnTypeExpected (si.Name, si2.Type, info.Properties["function_type"] as string); } else { // copy it in r1 si.Code.Append("addi r2,r14," + si2.Offset + "\nlw r1,stack(r2)\njr r15\n"); } } if (!error && p == 1) Log(LogType.Parse, "<statement> ::= return ( <expr> ) ;"); } else error = true; return !error; }
/// <summary> /// The main function. Runs the parser over the stream and /// returns whether or not the stream is valid. /// </summary> /// <returns>A bool indicating whether or not the stream is valid syntactically</returns> public bool Parse() { // first parse the program // phase 1 CompilerStack.Clear(); CompilerStack.Push(new StackFrame(this)); lexer.Reset(); lookahead = lexer.GetNextToken(); SemanticInfo si = new SemanticInfo(); bool ok1 = NTF_Prog(1, si) && Match(1, Lexer.Token.TokenType.EndOfFile); ComputeClassSizes(); // phase 2 CompilerStack.Clear(); CompilerStack.Push(new StackFrame(this)); si = new SemanticInfo(); lexer.Reset(); lookahead = lexer.GetNextToken(); bool ok2 = NTF_Prog(2, si) && Match(2, Lexer.Token.TokenType.EndOfFile); si.Code.Insert(0, "stack res 5000\nalign\n"); si.Code.Append( @" putint align add r2,r0,r0 % Initialize buffer's index i cge r3,r1,r0 % True if N >= 0 bnz r3,putint1 % Branch if True (N >= 0) sub r1,r0,r1 % N = -N putint1 modi r4,r1,10 % Rightmost digit addi r4,r4,48 % Convert to ch divi r1,r1,10 % Truncate rightmost digit sb putint9(r2),r4 % Store ch in buffer addi r2,r2,1 % i++ bnz r1,putint1 % Loop if not finished bnz r3,putint2 % Branch if True (N >= 0) addi r3,r0,45 sb putint9(r2),r3 % Store '-' in buffer addi r2,r2,1 % i++ add r1,r0,r0 % Initialize output register (r1 = 0) putint2 subi r2,r2,1 % i-- lb r1,putint9(r2) % Load ch from buffer putc r1 % Output ch bnz r2,putint2 % Loop if not finished addi r1,r0,13 % load new line putc r1 % print it addi r1,r0,10 % new feed thingie putc r1 jr r15 % return to the caller putint9 res 12 % loacl buffer (12 bytes) align getint add r1,r0,r0 % n := 0 (result) add r2,r0,r0 % c := 0 (character) add r3,r0,r0 % s := 0 (sign) getint1 getc r2 % read c ceqi r4,r2,32 bnz r4,getint1 % skip blanks ceqi r4,r2,43 bnz r4,getint2 % branch if c is '+' ceqi r4,r2,45 bz r4,getint3 % branch if c is not '-' addi r3,r0,1 % s := 1 (number is negative) getint2 getc r2 % read c getint3 ceqi r4,r2,10 bnz r4,getint5 % branch if c is \n cgei r4,r2,48 bz r4,getint4 % c < 0 clei r4,r2,57 bz r4,getint4 % c > 9 muli r1,r1,10 % n := 10 * n add r1,r1,r2 % n := n + c subi r1,r1,48 % n := n - '0' j getint2 getint4 addi r2,r0,63 % c := '?' putc r2 % write c j getint % Try again getint5 bz r3,getint6 % branch if s = 0 (number is positive) sub r1,r0,r1 % n := -n getint6 jr r15 % return "); Log(LogType.Code, si.Code.ToString()); // then write out the debug information Log(LogType.SymbolTable, Global.ToString()); foreach (string error in Errors) Log(LogType.Error, error); foreach (string warning in Warnings) Log(LogType.Warning, warning); // and flush the streams foreach (TextWriter tw in Output.Values) tw.Flush(); return ok1 && ok2; }
public override void CheckSemantic(SymbolTable symbolTable, List <CompileError> errors) { ///check semantics al StartIndex StartIndex.CheckSemantic(symbolTable, errors); ///check semantics al EndIndex EndIndex.CheckSemantic(symbolTable, errors); ///si StartIndex no evaluó de error if (!Object.Equals(StartIndex.NodeInfo, SemanticInfo.SemanticError)) { ///la expresión de StartIndex tiene que ser compatible con 'int' if (!StartIndex.NodeInfo.BuiltInType.IsCompatibleWith(BuiltInType.Int)) { errors.Add(new CompileError { Line = StartIndex.Line, Column = StartIndex.CharPositionInLine, ErrorMessage = string.Format("Cannot implicitly convert type '{0}' to 'int'", StartIndex.NodeInfo.Type.Name), Kind = ErrorKind.Semantic }); ///el nodo evalúa de error NodeInfo = SemanticInfo.SemanticError; } } ///si EndIndex no evaluó de error if (!Object.Equals(EndIndex.NodeInfo, SemanticInfo.SemanticError)) { ///la expresión de EndIndex tiene que ser compatible con 'int' if (!EndIndex.NodeInfo.BuiltInType.IsCompatibleWith(BuiltInType.Int)) { errors.Add(new CompileError { Line = EndIndex.Line, Column = EndIndex.CharPositionInLine, ErrorMessage = string.Format("Cannot implicitly convert type '{0}' to 'int'", EndIndex.NodeInfo.Type.Name), Kind = ErrorKind.Semantic }); ///el nodo evalúa de error NodeInfo = SemanticInfo.SemanticError; } } SemanticInfo loopVarInfo; ///no puede haber otra variable con el mismo nombre que este if (symbolTable.GetDefinedVariableDeep(LoopVariable, out loopVarInfo)) { errors.Add(new CompileError { Line = GetChild(0).Line, Column = GetChild(0).CharPositionInLine, ErrorMessage = string.Format("A local variable named '{0}' cannot be declared in this scope because it would give a different meaning to'{1}', which is already used in a 'parent or current' scope to denote something else", LoopVariable, LoopVariable), Kind = ErrorKind.Semantic }); } ///creamos un nuevo scope symbolTable.InitNewScope(); ///agregamos la variable de iteración al scope actual SemanticInfo loopVariable = new SemanticInfo { Name = LoopVariable, ElementKind = SymbolKind.Variable, IsReadOnly = true, //ponemos la variable como readonly BuiltInType = BuiltInType.Int, Type = SemanticInfo.Int }; symbolTable.InsertSymbol(loopVariable); ///check semantics al ForBody ForBody.CheckSemantic(symbolTable, errors); ///aquí concluye el scope que crea el for symbolTable.CloseCurrentScope(); ///si el ForBody evalúa de error este también if (Object.Equals(ForBody.NodeInfo, SemanticInfo.SemanticError)) { ///el nodo evalúa de error NodeInfo = SemanticInfo.SemanticError; return; } ///seteamos la información del NodeInfo NodeInfo.BuiltInType = BuiltInType.Void; NodeInfo.Type = SemanticInfo.Void; ///el ForBody no puede retornar valor if (ForBody.NodeInfo.BuiltInType.IsReturnType()) { errors.Add(new CompileError { Line = ForBody.Line, Column = ForBody.CharPositionInLine, ErrorMessage = "Body of control instruction 'for' cannot return value", Kind = ErrorKind.Semantic }); ///el nodo evalúa de error NodeInfo = SemanticInfo.SemanticError; } }
// <expr2> ::= e | relop <arithexpr> protected bool NTF_Expr2(int p, SemanticInfo si) { bool error = SkipErrors(p, Lexer.Token.TokenType.Comparison, Lexer.Token.TokenType.Semicolon, Lexer.Token.TokenType.CloseBracket); // first(<expr2>)=relop if (lookahead.Type == Lexer.Token.TokenType.Comparison) { string op = lookahead.Value; if (op == "<") op = "clt"; else if (op == "<=") op = "cle"; else if (op == ">") op = "cgt"; else if (op == ">=") op = "cge"; else if (op == "==") op = "ceq"; else if (op == "<>") op = "cne"; error |= !Match(p, Lexer.Token.TokenType.Comparison); SemanticInfo si2 = new SemanticInfo(); error |= !NTF_ArithExpr(p, si2); if (p == 2) { si.Code.Append(si2.Code); si.Code.Append("addi r3,r14," + si.Offset + "\nlw r1,stack(r3)\n" + "addi r3,r14," + si2.Offset + "\nlw r2,stack(r3)\n" + op + " r1,r1,r2\n"); CompilerStack.Peek().SafeFreeTemp(si.Offset); CompilerStack.Peek().SafeFreeTemp(si2.Offset); int tmp = CompilerStack.Peek().RequestTemp() + CompilerStack.Peek().GetTotalRealOffset(); si.Code.Append("addi r2,r14," + tmp + "\nsw stack(r2),r1\n"); si.Offset = tmp; } if (!error && p == 1) Log(LogType.Parse, "<expr2> ::= relop <arithexpr>"); } // follow(<expr2>)=follow(<expr>)=;+) else if (lookahead.Type == Lexer.Token.TokenType.Semicolon || lookahead.Type == Lexer.Token.TokenType.CloseBracket) { if (p == 1) Log(LogType.Parse, "<expr2> ::= e"); } else error = true; return !error; }
// <sign> ::= + | - protected bool NTF_Sign(int p, SemanticInfo si) { bool error = SkipErrors(p, "+", "-", Lexer.Token.TokenType.Identifier, Lexer.Token.TokenType.Number, Lexer.Token.TokenType.OpenBracket, Lexer.Token.TokenType.Not); if (lookahead.Value == "+") { error |= !Match(p, "+"); if (!error && p == 1) Log(LogType.Parse, "<sign> ::= +"); } else { error |= !Match(p, "-"); // TODO: fix unary - if (p == 2) SemanticError("unary - not working yet"); if (!error && p == 1) Log(LogType.Parse, "<sign> ::= -"); } return false; }
// <factor> ::= <idnest> <factor2> // | num // | ( <expr> ) // | ! <factor> protected bool NTF_Factor(int p, SemanticInfo si) { bool error = SkipErrors(p, Lexer.Token.TokenType.Identifier, Lexer.Token.TokenType.Number, Lexer.Token.TokenType.OpenBracket, Lexer.Token.TokenType.Not, Lexer.Token.TokenType.Multiplicative, Lexer.Token.TokenType.Comparison, Lexer.Token.TokenType.Additive, Lexer.Token.TokenType.Comma, Lexer.Token.TokenType.CloseBracket, Lexer.Token.TokenType.Semicolon); // first(<idneststar>)=id if (lookahead.Type == Lexer.Token.TokenType.Identifier) { error |= !NTF_IdNest(p, si); error |= !NTF_Factor2(p, si); if (!error && p == 1) Log(LogType.Parse, "<factor> ::= <idneststar> id <factor2>"); } else if (lookahead.Type == Lexer.Token.TokenType.Number) { if (p == 2) { // load the number si.Name = lookahead.Value; si.Type = lookahead.Value.IndexOf('.') >= 0 ? "float" : "int"; // TODO: make it work with floats si.Offset = CompilerStack.Peek().GetTotalRealOffset() + CompilerStack.Peek().RequestTemp(); si.Code.Append("addi r1,r0," + lookahead.Value + "\naddi r2,r14," + si.Offset + "\nsw stack(r2),r1\n"); } error |= !Match(p, Lexer.Token.TokenType.Number); if (!error && p == 1) Log(LogType.Parse, "<factor> ::= num"); } else if (lookahead.Type == Lexer.Token.TokenType.OpenBracket) { error |= !Match(p, Lexer.Token.TokenType.OpenBracket); error |= !NTF_Expr(p, si); error |= !Match(p, Lexer.Token.TokenType.CloseBracket); if (!error && p == 1) Log(LogType.Parse, "<factor> ::= ( <expr> )"); } else if (lookahead.Type == Lexer.Token.TokenType.Not) { error |= !Match(p, Lexer.Token.TokenType.Not); SemanticInfo si2 = new SemanticInfo(); error |= !NTF_Factor(p, si2); if (p == 2) { si.Code.Append(si2.Code); si.Code.Append("addi r2,r14," + si2.Offset + "\nlw r1,stack(r2)\nnot r1,r1\n"); CompilerStack.Peek().SafeFreeTemp(si2.Offset); string jmp_zero = GetNewJumpLabel(); si.Code.Append("bz r1," + jmp_zero + "\naddi r1,r0,1\n" + jmp_zero + " nop\n"); si.Offset = CompilerStack.Peek().RequestTemp(); si.Code.Append("addi r2,r14," + si.Offset + "\nsw stack(r2),r1\n"); } if (!error && p == 1) Log(LogType.Parse, "<factor> ::= ! <factor>"); } else error = true; return !error; }
// <prog> ::= <classdeclstar><progbody> protected bool NTF_Prog(int p, SemanticInfo si) { bool error = SkipErrors(p, "class", "program", Lexer.Token.TokenType.EndOfFile); error |= !NTF_ClassDeclStar(p, si); error |= !NTF_ProgBody(p, si); if (!error && p == 1) Log(LogType.Parse, "<prog> ::= <classdeclstar><progbody>"); return !error; }
public override void CheckSemantic(SymbolTable symbolTable, List <CompileError> errors) { ///la instrucción let-in-end genera un nuevo scope symbolTable.InitNewScope(); #region CheckSemantic_of_Declarations_List DeclarationNode currentDeclaration; DeclarationType previousDeclarationType = DeclarationType.NONE; List <DeclarationNode> pendingDeclarations = new List <DeclarationNode>(); ///chequeamos la semántica de C/U de las declaraciones for (int i = 0; i < LetDeclarationCount; i++) { currentDeclaration = GetLetDeclarationAt(i); if (GetDeclarationType(currentDeclaration) != previousDeclarationType && pendingDeclarations.Count > 0) { CommitPendingDeclarations(symbolTable, errors, pendingDeclarations); pendingDeclarations.Clear(); } if (GetDeclarationType(currentDeclaration) == DeclarationType.VARIABLE) { currentDeclaration.CheckSemantic(symbolTable, errors); } else { pendingDeclarations.Add(currentDeclaration); } previousDeclarationType = GetDeclarationType(currentDeclaration); } ///chequeamos el último bloque if (pendingDeclarations.Count > 0) { CommitPendingDeclarations(symbolTable, errors, pendingDeclarations); pendingDeclarations.Clear(); } #endregion ///chequeamos la semántica de ExpressionSequence ExpressionSequence.CheckSemantic(symbolTable, errors); ///si el ExpressionSequence evalúa de error, este también if (Object.Equals(ExpressionSequence.NodeInfo, SemanticInfo.SemanticError)) { ///el nodo evalúa de error NodeInfo = SemanticInfo.SemanticError; } ///el scope de let-in-end termina en el end symbolTable.CloseCurrentScope(); ///si este no evaluó de error if (!Object.Equals(NodeInfo, SemanticInfo.SemanticError)) { NodeInfo = new SemanticInfo { Name = SemanticInfo.NoName, BuiltInType = ExpressionSequence.NodeInfo.BuiltInType, ElementKind = SymbolKind.NoSymbol, Type = ExpressionSequence.NodeInfo.Type, ElementsType = ExpressionSequence.NodeInfo.ElementsType, Fields = ExpressionSequence.NodeInfo.Fields, //added ILType = ExpressionSequence.NodeInfo.ILType }; } }
private static SemanticInfo ExtractSemanticInfo(Type modelType) { SemanticInfo semanticInfo = new SemanticInfo(); // Built-in semantic type mapping string bareTypeName = modelType.Name.Split('`')[0]; // Type name without generic type parameters (if any) semanticInfo.MappedSemanticTypes.Add(SemanticMapping.GetQualifiedTypeName(bareTypeName)); // Extract semantic info from SemanticEntity attributes on the Model Type. foreach (SemanticEntityAttribute attribute in modelType.GetCustomAttributes(true).Where(a => a is SemanticEntityAttribute)) { semanticInfo.MappedSemanticTypes.Add(SemanticMapping.GetQualifiedTypeName(attribute.EntityName, attribute.Vocab)); if (!attribute.Public || string.IsNullOrEmpty(attribute.Prefix)) continue; string prefix = attribute.Prefix; string registeredVocab; if (semanticInfo.PrefixMappings.TryGetValue(prefix, out registeredVocab)) { // Prefix mapping already exists; must match. if (attribute.Vocab != registeredVocab) { throw new DxaException( string.Format("Attempt to use semantic prefix '{0}' for vocabulary '{1}', but is is already used for vocabulary '{2}", prefix, attribute.Vocab, registeredVocab) ); } } else { semanticInfo.PrefixMappings.Add(prefix, attribute.Vocab); } semanticInfo.PublicSemanticTypes.Add(String.Format("{0}:{1}", prefix, attribute.EntityName)); } // Extract semantic info from SemanticEntity attributes on the Model Type's properties foreach (MemberInfo memberInfo in modelType.GetMembers(BindingFlags.Public | BindingFlags.Instance)) { foreach (SemanticPropertyAttribute attribute in memberInfo.GetCustomAttributes(true).Where(a => a is SemanticPropertyAttribute)) { if (string.IsNullOrEmpty(attribute.PropertyName)) { // Skip properties without name. continue; } string[] semanticPropertyNameParts = attribute.PropertyName.Split(':'); if (semanticPropertyNameParts.Length < 2) { // Skip property names without prefix. continue; } string prefix = semanticPropertyNameParts[0]; if (!semanticInfo.PrefixMappings.ContainsKey(prefix)) { // Skip property names with prefix which is not declared as public prefix on the type. continue; } IList<string> semanticPropertyNames; if (!semanticInfo.SemanticProperties.TryGetValue(memberInfo.Name, out semanticPropertyNames)) { semanticPropertyNames = new List<string>(); semanticInfo.SemanticProperties.Add(memberInfo.Name, semanticPropertyNames); } semanticPropertyNames.Add(attribute.PropertyName); } } return semanticInfo; }
// <type> ::= int | float | id protected bool NTF_Type(int p, SemanticInfo si) { bool error = SkipErrors(p, "int", "float", Lexer.Token.TokenType.Identifier); if (lookahead.Value == "int") { si.Type = "int"; error |= !Match(p, "int"); if (!error && p == 1) Log(LogType.Parse, "<type> ::= int"); } else if (lookahead.Value == "float") { si.Type = "float"; error |= !Match(p, "float"); if (!error && p == 1) Log(LogType.Parse, "<type> ::= float"); } else if (lookahead.Type == Lexer.Token.TokenType.Identifier) { si.Type = lookahead.Value; error |= !Match(p, Lexer.Token.TokenType.Identifier); if (!error && p == 1) Log(LogType.Parse, "<type> ::= id"); } return !error; }
// <definitionstar> ::= e | <definition> <definitionstar> protected bool NTF_DefinitionStar(int p, SemanticInfo si) { bool error = SkipErrors(p, "int", "float", Lexer.Token.TokenType.Identifier, Lexer.Token.TokenType.CloseBrace, Lexer.Token.TokenType.EndOfFile); if (lookahead.Value == "int" || lookahead.Value == "float" || lookahead.Type == Lexer.Token.TokenType.Identifier) { error |= !NTF_Definition(p, si); error |= !NTF_DefinitionStar(p, si); if (!error && p == 1) Log(LogType.Parse, "<definitionstar> ::= <definition> <definitionstar>"); } // follow=}+$ else if (lookahead.Type == Lexer.Token.TokenType.EndOfFile || lookahead.Type == Lexer.Token.TokenType.CloseBrace) { if (p == 1) Log(LogType.Parse, "<definitionstar> ::= e"); } else error = true; return !error; }
// <typedecl> ::= <type> id <arraystar>; protected bool NTF_TypeDecl(int p) { bool error = SkipErrors(p, "int", "float", Lexer.Token.TokenType.Identifier, "if", "cin", "cout", "return", "for", Lexer.Token.TokenType.CloseBrace); SemanticInfo si = new SemanticInfo(); error |= !NTF_Type(p, si); si.Name = lookahead.Value; error |= !Match(p, Lexer.Token.TokenType.Identifier); error |= !NTF_ArrayStar(p, si); error |= !Match(p, Lexer.Token.TokenType.Semicolon); if (p == 1) { SymbolTable.Information info; if ((info = CurrentScope.Find(si.Name, false)) != null) SemanticErrorSymbolAlreadyDefined(si.Name); else { info = CurrentScope.Add(si.Name); info.Kind = SymbolTable.Information.EKind.Variable; info.Properties.Add("variable_type", si.Type); info.Properties.Add("variable_arrayindices", si.ArrayIndices.ToArray()); // TODO: account for objects bigger than 4 (word) //info.Properties.Add("variable_offset", CompilerStack.Peek().GetTotalRealOffset()); } } if (!error && p == 1) Log(LogType.Parse, "<typedecl> ::= <type> id <arraystar>;"); return !error; }