protected IrisType ParseFactor(SymbolLoadMode mode) { Operator opr = AcceptOperator(OperatorMaps.Instance.Factor); FilePosition fp = _lexer.TokenStartPosition; IrisType type = ParseBaseExpression(mode); if (opr != Operator.None) { type = DerefType(type); if (type == IrisType.String) { AddError(fp, "Unary operators cannot be applied to string values."); } else if (opr == Operator.Not) { VerifyExpressionType(fp, type, IrisType.Boolean); } else if (opr == Operator.Negate && type == IrisType.Boolean) { AddError(fp, "Unary negate operator cannot be applied to boolean values."); } MethodGenerator.Operator(opr); } return(type); }
protected IrisType ParseTerm(SymbolLoadMode mode) { IrisType lhs = ParseFactor(mode); FilePosition fp = _lexer.TokenStartPosition; Operator opr = AcceptOperator(OperatorMaps.Instance.Term); if (opr != Operator.None) { IrisType rhs = ParseTerm(mode); return(ProcessArithemticOperator(fp, lhs, rhs, opr)); } return(lhs); }
protected IrisType ParseExpression(SymbolLoadMode mode = SymbolLoadMode.Dereference) { IrisType lhs = ParseCompareExpression(mode); FilePosition fp = _lexer.TokenStartPosition; Operator opr = AcceptOperator(OperatorMaps.Instance.Logic); if (opr != Operator.None) { VerifyExpressionType(fp, lhs, IrisType.Boolean); IrisType rhs = ParseExpression(mode); VerifyExpressionType(fp, rhs, IrisType.Boolean); MethodGenerator.Operator(opr); } return(lhs); }
private IrisType ProcessArrayAccess(FilePosition fp, Symbol symbol, SymbolLoadMode mode) { IrisType symbolType = symbol.Type; IrisType resultType = IrisType.Invalid; if (symbolType != IrisType.Invalid) { if (!symbolType.IsArray) { AddError(fp, string.Format("Symbol '{0}' is not an array, but is being used as an array.", _lexeme)); } else { EmitLoadSymbol(symbol, SymbolLoadMode.Dereference); resultType = symbol.Type.GetElementType(); } } FilePosition indexerPosition = _lexer.TokenStartPosition; IrisType indexerType = ParseExpression(); if (indexerType != IrisType.Integer) { AddError(indexerPosition, "Expecting integer value as array index."); } Expect(Token.ChrCloseBracket); if (resultType != IrisType.Invalid) { if (mode == SymbolLoadMode.ElementAddress) { MethodGenerator.LoadElementAddress(resultType); resultType = resultType.MakeByRefType(); } else if (mode == SymbolLoadMode.Element) { MethodGenerator.LoadElement(resultType); } } return(resultType); }
protected void EmitLoadSymbol(Symbol symbol, SymbolLoadMode mode) { bool isByRef = symbol.Type.IsByRef; if (symbol.StorageClass == StorageClass.Argument) { if (mode == SymbolLoadMode.Address && !isByRef) { MethodGenerator.PushArgumentAddress(symbol.Location); } else { MethodGenerator.PushArgument(symbol.Location); } } else if (symbol.StorageClass == StorageClass.Local) { if (mode == SymbolLoadMode.Address && !isByRef) { MethodGenerator.PushLocalAddress(symbol.Location); } else { MethodGenerator.PushLocal(symbol.Location); } } else { if (mode == SymbolLoadMode.Address && !isByRef) { MethodGenerator.PushGlobalAddress(symbol); } else { MethodGenerator.PushGlobal(symbol); } } if (mode == SymbolLoadMode.Dereference && isByRef) { MethodGenerator.Load(symbol.Type.GetElementType()); } }
protected IrisType ParseCompareExpression(SymbolLoadMode mode) { IrisType lhs = ParseArithmeticExpression(mode); FilePosition fp = _lexer.TokenStartPosition; Operator opr = AcceptOperator(OperatorMaps.Instance.Compare); if (opr != Operator.None) { IrisType rhs = ParseCompareExpression(mode); if (lhs == IrisType.String && rhs == IrisType.String) { Symbol strcmp = LookupSymbol(fp, "strcmp"); MethodGenerator.Call(strcmp); MethodGenerator.PushIntConst(0); } MethodGenerator.Operator(opr); return(ApplyTypeRules(fp, lhs, rhs, boolResult: true)); } return(lhs); }
private IrisType ProcessArrayAccess(FilePosition fp, Symbol symbol, SymbolLoadMode mode) { IrisType symbolType = symbol.Type; IrisType resultType = IrisType.Invalid; if (symbolType != IrisType.Invalid) { if (!symbolType.IsArray) { AddError(fp, string.Format("Symbol '{0}' is not an array, but is being used as an array.", _lexeme)); } else { EmitLoadSymbol(symbol, SymbolLoadMode.Dereference); resultType = symbol.Type.GetElementType(); } } FilePosition indexerPosition = _lexer.TokenStartPosition; IrisType indexerType = ParseExpression(); if (indexerType != IrisType.Integer) AddError(indexerPosition, "Expecting integer value as array index."); Expect(Token.ChrCloseBracket); if (resultType != IrisType.Invalid) { if (mode == SymbolLoadMode.ElementAddress) { MethodGenerator.LoadElementAddress(resultType); resultType = resultType.MakeByRefType(); } else if (mode == SymbolLoadMode.Element) { MethodGenerator.LoadElement(resultType); } } return resultType; }
protected IrisType ParseBaseExpression(SymbolLoadMode mode) { FilePosition fp = _lastParsedPosition; if (Accept(Token.Identifier)) { Symbol symbol = LookupSymbol(fp, _lexeme); if (Accept(Token.ChrOpenBracket)) return ProcessArrayAccess(fp, symbol, mode == SymbolLoadMode.Address ? SymbolLoadMode.ElementAddress : SymbolLoadMode.Element); if (Accept(Token.ChrOpenParen)) return ProcessCall(fp, symbol, skipArgList: false); IrisType type = symbol.Type; if (type.IsMethod) return ProcessCall(fp, symbol, skipArgList: true); if (type != IrisType.Invalid) EmitLoadSymbol(symbol, mode); if (mode == SymbolLoadMode.Address && !type.IsByRef) return type.MakeByRefType(); else if (mode == SymbolLoadMode.Dereference) return DerefType(type); else return type; } else if (Accept(Token.KwTrue)) { MethodGenerator.PushIntConst(1); return IrisType.Boolean; } else if (Accept(Token.KwFalse)) { MethodGenerator.PushIntConst(0); return IrisType.Boolean; } else if (Accept(Token.Number)) { MethodGenerator.PushIntConst(_lastIntegerLexeme); return IrisType.Integer; } else if (Accept(Token.String)) { MethodGenerator.PushString(_lexeme); return IrisType.String; } else if (Accept(Token.ChrOpenParen)) { IrisType type = ParseExpression(mode); Expect(Token.ChrCloseParen); return type; } AddError(fp, "Expecting expression."); return IrisType.Invalid; }
protected IrisType ParseFactor(SymbolLoadMode mode) { Operator opr = AcceptOperator(OperatorMaps.Instance.Factor); FilePosition fp = _lexer.TokenStartPosition; IrisType type = ParseBaseExpression(mode); if (opr != Operator.None) { type = DerefType(type); if (type == IrisType.String) AddError(fp, "Unary operators cannot be applied to string values."); else if (opr == Operator.Not) VerifyExpressionType(fp, type, IrisType.Boolean); else if (opr == Operator.Negate && type == IrisType.Boolean) AddError(fp, "Unary negate operator cannot be applied to boolean values."); MethodGenerator.Operator(opr); } return type; }
protected IrisType ParseTerm(SymbolLoadMode mode) { IrisType lhs = ParseFactor(mode); FilePosition fp = _lexer.TokenStartPosition; Operator opr = AcceptOperator(OperatorMaps.Instance.Term); if (opr != Operator.None) { IrisType rhs = ParseTerm(mode); return ProcessArithemticOperator(fp, lhs, rhs, opr); } return lhs; }
protected IrisType ParseCompareExpression(SymbolLoadMode mode) { IrisType lhs = ParseArithmeticExpression(mode); FilePosition fp = _lexer.TokenStartPosition; Operator opr = AcceptOperator(OperatorMaps.Instance.Compare); if (opr != Operator.None) { IrisType rhs = ParseCompareExpression(mode); if (lhs == IrisType.String && rhs == IrisType.String) { Symbol strcmp = LookupSymbol(fp, "strcmp"); MethodGenerator.Call(strcmp); MethodGenerator.PushIntConst(0); } MethodGenerator.Operator(opr); return ApplyTypeRules(fp, lhs, rhs, boolResult: true); } return lhs; }
protected IrisType ParseExpression(SymbolLoadMode mode = SymbolLoadMode.Dereference) { IrisType lhs = ParseCompareExpression(mode); FilePosition fp = _lexer.TokenStartPosition; Operator opr = AcceptOperator(OperatorMaps.Instance.Logic); if (opr != Operator.None) { VerifyExpressionType(fp, lhs, IrisType.Boolean); IrisType rhs = ParseExpression(mode); VerifyExpressionType(fp, rhs, IrisType.Boolean); MethodGenerator.Operator(opr); } return lhs; }
protected void EmitLoadSymbol(Symbol symbol, SymbolLoadMode mode) { bool isByRef = symbol.Type.IsByRef; if (symbol.StorageClass == StorageClass.Argument) { if (mode == SymbolLoadMode.Address && !isByRef) MethodGenerator.PushArgumentAddress(symbol.Location); else MethodGenerator.PushArgument(symbol.Location); } else if (symbol.StorageClass == StorageClass.Local) { if (mode == SymbolLoadMode.Address && !isByRef) MethodGenerator.PushLocalAddress(symbol.Location); else MethodGenerator.PushLocal(symbol.Location); } else { if (mode == SymbolLoadMode.Address && !isByRef) MethodGenerator.PushGlobalAddress(symbol); else MethodGenerator.PushGlobal(symbol); } if (mode == SymbolLoadMode.Dereference && isByRef) MethodGenerator.Load(symbol.Type.GetElementType()); }
protected IrisType ParseBaseExpression(SymbolLoadMode mode) { FilePosition fp = _lastParsedPosition; if (Accept(Token.Identifier)) { Symbol symbol = LookupSymbol(fp, _lexeme); if (Accept(Token.ChrOpenBracket)) { return(ProcessArrayAccess(fp, symbol, mode == SymbolLoadMode.Address ? SymbolLoadMode.ElementAddress : SymbolLoadMode.Element)); } if (Accept(Token.ChrOpenParen)) { return(ProcessCall(fp, symbol, skipArgList: false)); } IrisType type = symbol.Type; if (type.IsMethod) { return(ProcessCall(fp, symbol, skipArgList: true)); } if (type != IrisType.Invalid) { EmitLoadSymbol(symbol, mode); } if (mode == SymbolLoadMode.Address && !type.IsByRef) { return(type.MakeByRefType()); } else if (mode == SymbolLoadMode.Dereference) { return(DerefType(type)); } else { return(type); } } else if (Accept(Token.KwTrue)) { MethodGenerator.PushIntConst(1); return(IrisType.Boolean); } else if (Accept(Token.KwFalse)) { MethodGenerator.PushIntConst(0); return(IrisType.Boolean); } else if (Accept(Token.Number)) { MethodGenerator.PushIntConst(_lastIntegerLexeme); return(IrisType.Integer); } else if (Accept(Token.String)) { MethodGenerator.PushString(_lexeme); return(IrisType.String); } else if (Accept(Token.ChrOpenParen)) { IrisType type = ParseExpression(mode); Expect(Token.ChrCloseParen); return(type); } AddError(fp, "Expecting expression."); return(IrisType.Invalid); }