private void ParseStructDeclarationList() { Symbols.Type type = null; Symbols.Var variable = null; Pair <Symbols.Var, Pair <Symbols.RefType, Symbols.RefType> > pair = null; while (IsType(scan.Peek()) && (type = ParseTypeSpecifier()) != null) { while (true) { pair = ParseDeclarator(); variable = pair.first; if (pair.last == null) { variable.SetType(type); } else { pair.last.last.SetType(type); variable.SetType(pair.last.first); } tstack.AddSymbol(variable); if (scan.Peek().type != Token.Type.COMMA) { break; } scan.Read(); } CheckToken(scan.Peek(), Token.Type.SEMICOLON, true); } }
private static Pair <Expression, Expression> UsualArithmeticConversions( Expression lop, Expression rop) { Symbols.Type lt = lop.GetType(), rt = rop.GetType(); if (lt is Symbols.DOUBLE || rt is Symbols.DOUBLE) { if (rt != lt) { if (lt is Symbols.DOUBLE) { rop = new Cast(rop, lt); } else { lop = new Cast(lop, rt); } } } else if (lt is Symbols.CHAR && rt is Symbols.INT) { lop = new Cast(lop, rt); } else if (rt is Symbols.CHAR && lt is Symbols.INT) { rop = new Cast(rop, lt); } return(new Pair <Expression, Expression>(lop, rop)); }
private Param Param() { bool isOpt = Except(Tag.OPTIONAL); Word name = look as Word; ExceptGrammar(Tag.IDENTITY); ExceptGrammar(Tag.AS); Symbols.Type type = look as Symbols.Type; ExceptGrammar(Tag.BASICTYPE); if (isOpt && ExceptGrammar(Tag.Equal)) { Expr initVal = Expr(); if (!(initVal is Constant)) { throw new TokenNotConstantException(initVal); } Except(Tag.Split); return(new OptParam(name, type, initVal as Constant)); } else { Except(Tag.Split); return(new Param(name, type)); } }
private Symbols.ParamVar ParseParameterDeclaration() { Token first_token = scan.Peek(); Symbols.Type type = ParseTypeSpecifier(); Symbols.ParamVar variable = null; if (type != null) { Pair <Symbols.Var, Pair <Symbols.RefType, Symbols.RefType> > res; res = ParseDeclarator(parse_parameter: true); variable = (Symbols.ParamVar)res.first; if (res.last != null) { res.last.last.SetType(type); type = res.last.first; } if (type is Symbols.VOID) { this.logger.Add(new Symbols.Exception("недопустимо использование типа \"void\"", first_token.GetIndex(), first_token.GetLine())); type = new Symbols.SuperType(); } if (variable == null) { variable = new Symbols.ParamVar("", type.GetIndex(), type.GetLine()); } } variable.SetType(type); return(variable); }
public Id(Word id, SymbolTable t, Symbols.Type p, int b, bool s) : base(id, p) { Offset = b; Scope = t; IsStatic = s; Identity = id; IsInitial = false; }
public Params(int line, IEnumerable <Param> args, Symbols.Type retType) : base(line) { ParamList = args; ReturnType = retType; if (ReturnType == null) { ReturnType = ReserveType.Void; } }
public void Value(Symbols.Type t_val) { Reg r = GetFreeReg(); AddCode(Com.POP, new Addr(r)); if (t_val is Symbols.INT || t_val is Symbols.POINTER || t_val is Symbols.CHAR) { AddCode(Com.PUSH, new Val(new Addr(r), t_val.GetSizeType())); } else if (t_val is Symbols.DOUBLE) { AddCode(Com.SUB, new Addr(Reg.ESP), new Val(8, size: 4)); AddCode(Com.MOV, new Addr(Reg.ESP), new Val(new Addr(r), size: 8)); } }
private bool IsType(Token t) { switch (t.type) { case Token.Type.KW_STRUCT: case Token.Type.KW_ENUM: return(true); default: Symbols.Type tt = null; if (tstack.ContainsType(t.GetStrVal())) { tt = tstack.GetType(t.GetStrVal()); } return(tt != null && !(tt is Symbols.Func)); } }
public static BinaryConvertResult PostfixConvertResult(Expression lop, Expression rop, PostfixOperator op) { BinaryConvertResult res = new BinaryConvertResult(); switch (op) { case PostfixOperator.REF: case PostfixOperator.DOT: Symbols.Type t = lop.GetType() is Symbols.POINTER && op == PostfixOperator.REF? ((Symbols.POINTER)lop.GetType()).GetRefType() : lop.GetType(); if (!(t is Symbols.RECORD)) { throw new Symbols.Exception(lop, NOT_STRUCT); } if (!((Symbols.RECORD)t).GetTable().ContainsVariable(((Identifier)rop).GetName())) { throw new Symbols.Exception(rop, string.Format(NOT_MEMBER, ((Identifier)rop).GetName(), t.GetName()) ); } res.lvalue = true; res.type = (((Symbols.RECORD)t).GetTable().GetVariable(((Identifier)rop).GetName())).GetType(); break; case PostfixOperator.INDEX: if (!(lop.GetType() is Symbols.POINTER)) { throw new Symbols.Exception(lop, NOT_POINTER); } if (!rop.GetType().IsInteger()) { throw new Symbols.Exception(rop, NOT_INTEGER); } res.lvalue = true; res.type = ((Symbols.RefType)lop.GetType()).GetRefType(); break; } res.left = lop; res.right = rop; return(res); }
private void ParseTypedefs() { while (scan.Peek().type == Token.Type.KW_TYPEDEF) { Symbols.TYPEDEF typedef = new Symbols.TYPEDEF(scan.Read()); Symbols.Type type = ParseTypeSpecifier(); Pair <Symbols.Var, Pair <Symbols.RefType, Symbols.RefType> > pair = ParseDeclarator(); if (pair.last != null) { pair.last.last.SetType(type); type = pair.last.first; } typedef.SetName(pair.first.GetName()); typedef.SetType(type); tstack.AddSymbol(typedef); CheckToken(scan.Peek(), Token.Type.SEMICOLON, true); } }
private Access Offset(Id a) { Expr i, t1, t2, loc; Symbols.Type type = a.Type; i = Bool(); ExceptGrammar(Tag.RightBar); type = (type as Symbols.Array).Type; t1 = new Constant(type.Width); loc = t1; while (Except(Tag.LeftBra)) { i = Bool(); ExceptGrammar(Tag.RightBar); t1 = new Constant(type.Width); t2 = new Arith(new Token('+', a.lexline, 0), loc, t1); } return(new Access(a, loc, type)); }
void dims(ref Symbols.Type p, Word name) { Number size = look as Number; if (ExceptGrammar(Tag.NUMBER)) { if (ExceptGrammar(Tag.RightBar)) { if (Except(Tag.LeftBra)) { dims(ref p, name); } p = new Symbols.Array(p, size.value); } else { throw new TokenNotCloseArrayException(name); } } }
public static void CheckCallFunction(Expression func, List <Expression> args) { Symbols.Type t = func.GetType(); if (!(t is Symbols.Func || (t is Symbols.POINTER && ((Symbols.POINTER)t).GetRefType() is Symbols.Func))) { throw new Symbols.Exception(func, NOT_FUNCTION); } Symbols.Func f = (Symbols.Func)(t is Symbols.Func ? t : ((Symbols.POINTER)t).GetRefType()); List <Symbols.ParamVar> f_args = f.GetArguments(); if (f_args.Count != args.Count && !f.IsUnspecifiedArgs()) { throw new Symbols.Exception(func, WRONG_NUMBER_ARGS); } for (int i = 0; i < f_args.Count; ++i) { new Cast(args.ElementAt(i), f_args.ElementAt(i).GetType()); } }
private Params Params() { Symbols.Type type = ReserveType.Void; List <Param> param = new List <Param>(); ExceptGrammar(Tag.LeftPar); Token cur = look; while (Test(Tag.IDENTITY, Tag.OPTIONAL)) { Param p = Param(); param.Add(p); top.Add(p.ParamName.lexeme, new Id(p, top, 0, false)); } ExceptGrammar(Tag.RightPar); if (Except(Tag.AS)) { //just support reserve type type = look as Symbols.Type; ExceptGrammar(Tag.BASICTYPE); } return(new Params(cur.Line, param, type)); }
public Constant(Token tok, Symbols.Type p) : base(tok, p) { }
public Temp(Symbols.Type p) : base(Word.Temp, p) { number = ++count; }
public Op(Token tok, Symbols.Type p) : base(tok, p) { }
public IdFunc(Function func, Word id, SymbolTable t, Symbols.Type p, int b, bool s) : base(id, t, p, b, s) { Func = func; }
public RETURN(Symbols.Type ret_type) { this.ret_type = ret_type; }
public static UnaryConvertResult ConvertUnaryOperand(Expression operand, Token op) { UnaryConvertResult res = new UnaryConvertResult(); Symbols.Type t = operand.GetType(); switch (op.type) { case Token.Type.OP_INC: case Token.Type.OP_DEC: Token.Type tt = op.type == Token.Type.OP_DEC ? Token.Type.OP_SUB_ASSIGN : Token.Type.OP_PLUS_ASSIGN; BinaryOperator bop = new BinaryOperator(new Token(tt)); bop.SetLeftOperand(operand); bop.SetRightOperand(new Const("1", new Symbols.INT())); res.type = bop.GetType(); break; case Token.Type.OP_BIT_AND: if (!(operand.IsLvalue() || operand.GetType() is Symbols.Func)) { throw new Symbols.Exception(operand, NOT_LVALUE_OR_FUNC); } res.type = new Symbols.POINTER(operand.GetType()); break; case Token.Type.OP_STAR: res.lvalue = true; if (!(t is Symbols.POINTER || t is Symbols.Func)) { throw new Symbols.Exception(operand, NOT_POINTER); } if (t is Symbols.Func) { res.type = t; } else { res.type = ((Symbols.RefType)t).GetRefType(); } break; case Token.Type.OP_PLUS: case Token.Type.OP_SUB: if (!t.IsArifmetic()) { throw new Symbols.Exception(operand, NOT_ARITHMETICAL); } res.type = t; break; case Token.Type.OP_TILDE: if (!t.IsInteger()) { throw new Symbols.Exception(operand, NOT_INTEGER); } res.type = t; break; case Token.Type.OP_NOT: if (!(t.IsArifmetic() || t is Symbols.Func || t is Symbols.POINTER)) { throw new Symbols.Exception(operand, string.Format(NO_OPERATOR, op.GetStrVal())); } res.type = new Symbols.INT(); break; case Token.Type.KW_SIZEOF: res.type = new Symbols.INT(); break; case Token.Type.OP_DOT: default: throw new System.NotImplementedException(); } res.operand = operand; return(res); }
public void SetTypeCast(Symbols.Type type) { this.type_cast = type; this.type = type; CheckOperands(); }
public static void CheckCast(Symbols.Type type, Symbols.Type cast_type) { }
public TypeCovertException(int line, Symbols.Type T1, Symbols.Type T2) : base("Ln " + line + ", Type " + T1 + " cannot convert to " + T2) { }
public TypeMisMatchException(int line, Symbols.Type T, string except) : base("Ln " + line + ", Type " + T + " not match covert rule (except: " + except.ToString() + ")") { }
private void ParseDeclaration() { while (scan.Peek().type == Token.Type.SEMICOLON) { scan.Read(); } if (scan.Peek().type == Token.Type.EOF) { return; } Token first_token = scan.Peek(); Symbols.Type type = ParseTypeSpecifier(), variable_type = null; Pair<Symbols.Var, Pair<Symbols.RefType, Symbols.RefType>> pair = null; bool function = true; while (true) { variable_type = type; if ((pair = ParseDeclarator()) != null) { if (pair.last != null) { pair.last.last.SetType(type); variable_type = pair.last.first; } ///Когда мы устанавливаем финальный тип, то нужно пересчитать размер всех типов if (pair.first == null && !(variable_type is Symbols.RECORD)) { throw new Syntax.Exception("требуется идентификатор", scan.GetPos(), scan.GetLine()); } if (pair.first != null) { pair.first.SetType(variable_type); } if (scan.Peek().type == Token.Type.OP_ASSIGN) // init declarator { Symbols.Var v = pair.first; Syntax.Expression node = new Syntax.Identifier( new Token(v.GetIndex(), v.GetLine(), Token.Type.IDENTIFICATOR, v.GetName()), v ); node = ParseBinaryOper(0, node, true); //pair.first.SetInitializer(ParseInitializer()); pair.first.SetInitializer(node); function = false; } if (function && scan.Peek().type == Token.Type.LBRACE && tstack.IsGlobal()) { pair.last.first.SetName(pair.first.GetName()); tstack.AddSymbol(pair.first); tstack.NewTable(); if (((Symbols.Func)pair.last.first).GetArguments() .Count(x => x.GetName() == pair.first.GetName()) == 0) { tstack.AddSymbol(pair.first); } foreach (Symbols.Var arg in ((Symbols.Func)pair.last.first).GetArguments()) { tstack.AddSymbol(arg); } this.ret_func_type = ((Symbols.Func)pair.last.first).GetRefType(); ((Symbols.Func)pair.last.first).SetBody(ParseCompound(false)); tstack.GetCurrentTable().RemoveSymbol(pair.first); ((Symbols.Func)pair.last.first).SetTable(tstack.PopTable()); } else { function = false; } if (!function && variable_type is Symbols.VOID) { throw new Symbols.Exception("недопустимо использование типа \"void\"", first_token.GetIndex(), first_token.GetLine()); } if (pair.first != null && !function) { try { tstack.AddSymbol(pair.first); } catch (Symbols.Exception e) { this.logger.Add(e); } } } if (scan.Peek().type != Token.Type.COMMA || function) { break; } scan.Read(); function = false; } if (!function) { CheckToken(scan.Peek(), Token.Type.SEMICOLON, true); } }
public Access(Id a, Expr i, Symbols.Type p) : base(new Word(Tag.ARRAY, "[]", a.Op.Line, a.Op.Pos), p) { array = a; index = i; }
public Expr(Token tok, Symbols.Type p) : base(tok.Line) { Op = tok; Type = p; }
void reserve(Symbols.Type t) { words.Add(t.lexeme, t); }
public Param(Word name, Symbols.Type type) : base(name.Line) { ParamName = name; ParamType = type; }
private Stmt stmt() { Expr x; Stmt s1, s2; Stmt saveStmt; if (Except(Tag.IF)) { ExceptGrammar(Tag.LeftPar); x = Bool(); ExceptGrammar(Tag.RightPar); s1 = stmt(); if (!Except(Tag.ELSE)) { return(new If(x, s1)); } s2 = stmt(); return(new Else(x, s1, s2)); } else if (Except(Tag.WHILE)) { While node = new While(look.Line); saveStmt = Stmt.Encloseing; Stmt.Encloseing = node; ExceptGrammar(Tag.LeftPar); x = Bool(); ExceptGrammar(Tag.RightPar); s1 = stmt(); node.Init(x, s1); Stmt.Encloseing = saveStmt; return(node); } else if (Except(Tag.DO)) { Do node = new Do(look.Line); saveStmt = Stmt.Encloseing; Stmt.Encloseing = node; s1 = stmt(); ExceptGrammar(Tag.WHILE); ExceptGrammar(Tag.LeftPar); x = Bool(); ExceptGrammar(Tag.RightPar); node.Init(s1, x); Stmt.Encloseing = saveStmt; return(node); } else if (Except(Tag.DIM)) { bool isStatic = Except(Tag.STATIC); Word curName = look as Word; ExceptGrammar(Tag.IDENTITY); ExceptGrammar(Tag.AS); Symbols.Type type = look as Symbols.Type; ExceptGrammar(Tag.BASICTYPE); if (Except(Tag.LeftBra)) { // is array dims(ref type, curName); } Id id = new Id(curName, top, type, used, isStatic); top.Add(curName.lexeme, id); used += type.Width; if (Except(Tag.Equal)) { //a init val x = Bool(); return(new Set(id, x)); } return(Stmt.Null); } else if (Except(Tag.RETURN)) { Return ret; if (reader.ReadLast().TokenTag != Tag.LINE_END) { ret = new Return(look.Line, Stmt.LastFunction as Function, Bool()); return(ret); } else { move(); return(new Return(look.Line)); } } else if (Except(Tag.BREAK)) { return(new Break(look.Line)); } else if (Except(Tag.CONTINUE)) { return(new Continue(look.Line)); } else if (Except(Tag.LeftBlock)) { return(Block()); } else { return(Assign()); } }
public void SetType(Symbols.Type type) { this.type = type; }
public void Param(Param id, Symbols.Type t) { peekParam += t + " " + id + ","; }
public static BinaryConvertResult ConvertBinaryOperands(Expression lop, Expression rop, Token op) { Symbols.Type lt = lop.GetType(), rt = rop.GetType(); BinaryConvertResult res = new BinaryConvertResult(); res.op = op; Pair <Expression, Expression> uacon = null; switch (op.type) { case Token.Type.OP_STAR: case Token.Type.OP_DIV: if (!lt.IsArifmetic()) { throw new Symbols.Exception(lop, NOT_ARITHMETICAL); } if (!rt.IsArifmetic()) { throw new Symbols.Exception(rop, NOT_ARITHMETICAL); } if (op.type == Token.Type.OP_MOD) { if (!lt.IsArifmetic()) { lop = new Cast(lop, new Symbols.INT()); } if (!rt.IsArifmetic()) { rop = new Cast(rop, new Symbols.INT()); } res.type = rop.GetType(); break; } uacon = UsualArithmeticConversions(lop, rop); lop = uacon.first; rop = uacon.last; res.type = lop.GetType(); break; case Token.Type.OP_MOD: if (!lt.IsInteger()) { throw new Symbols.Exception(lop, NOT_INTEGER); } if (!rt.IsInteger()) { throw new Symbols.Exception(rop, NOT_INTEGER); } if (op.type == Token.Type.OP_MOD) { if (!(lt is Symbols.INT)) { lop = new Cast(lop, new Symbols.INT()); } if (!(rt is Symbols.INT)) { rop = new Cast(rop, new Symbols.INT()); } res.type = rop.GetType(); break; } uacon = UsualArithmeticConversions(lop, rop); lop = uacon.first; rop = uacon.last; res.type = lop.GetType(); break; case Token.Type.OP_PLUS: case Token.Type.OP_SUB: if (rt is Symbols.POINTER || lt is Symbols.POINTER) { if (rt is Symbols.POINTER && lt is Symbols.POINTER) { if (op.type == Token.Type.OP_PLUS) { throw new Symbols.Exception(lop, NOT_ARITHMETICAL); } res.type = rt; break; } BinaryOperator binop = new BinaryOperator(new Token(Token.Type.OP_STAR)); int size = 0; if (rt is Symbols.POINTER) { lop = lt is Symbols.INT ? lop : new Cast(lop, new Symbols.INT()); binop.SetLeftOperand(lop); size = ((Symbols.POINTER)rt).GetRefType().GetSizeType(); binop.SetRightOperand(new Const(size.ToString(), new Symbols.INT())); lop = binop; res.type = rt; } else { rop = rt is Symbols.INT ? rop : new Cast(rop, new Symbols.INT()); binop.SetLeftOperand(rop); size = ((Symbols.POINTER)lt).GetRefType().GetSizeType(); binop.SetRightOperand(new Const(size.ToString(), new Symbols.INT())); rop = binop; res.type = lt; } break; } if (lt.IsArifmetic() || rt.IsArifmetic()) { if (!lt.IsArifmetic()) { throw new Symbols.Exception(lop, NOT_ARITHMETICAL); } if (!rt.IsArifmetic()) { throw new Symbols.Exception(rop, NOT_ARITHMETICAL); } uacon = UsualArithmeticConversions(lop, rop); lop = uacon.first; rop = uacon.last; res.type = lop.GetType(); break; } if (lt is Symbols.Func || (lt is Symbols.POINTER && ((Symbols.POINTER)lt).GetRefType() is Symbols.Func)) { throw new Symbols.Exception(lop, NOT_COMPLETE_TYPE); } if (rt is Symbols.Func || (rt is Symbols.POINTER && ((Symbols.POINTER)rt).GetRefType() is Symbols.Func)) { throw new Symbols.Exception(rop, NOT_COMPLETE_TYPE); } throw new Symbols.Exception(lop, string.Format(NO_OPERATOR, op.GetStrVal())); case Token.Type.OP_L_SHIFT: case Token.Type.OP_R_SHIFT: case Token.Type.OP_BIT_AND: case Token.Type.OP_BIT_OR: case Token.Type.OP_XOR: if (!lt.IsInteger()) { throw new Symbols.Exception(lop, NOT_ARITHMETICAL); } if (!rt.IsInteger()) { throw new Symbols.Exception(rop, NOT_ARITHMETICAL); } uacon = UsualArithmeticConversions(lop, rop); lop = uacon.first; rop = uacon.last; res.type = lop.GetType(); break; case Token.Type.OP_MORE: case Token.Type.OP_LESS: case Token.Type.OP_LESS_OR_EQUAL: case Token.Type.OP_MORE_OR_EQUAL: case Token.Type.OP_EQUAL: case Token.Type.OP_NOT_EQUAL: uacon = UsualArithmeticConversions(lop, rop); lop = uacon.first; rop = uacon.last; res.type = lop.GetType(); break; case Token.Type.OP_AND: case Token.Type.OP_OR: if (!(lt.IsArifmetic() || lt is Symbols.POINTER)) { throw new Symbols.Exception(lop, string.Format(NO_OPERATOR, op.GetStrVal())); } if (!(rt.IsArifmetic() || rt is Symbols.POINTER)) { throw new Symbols.Exception(rop, string.Format(NO_OPERATOR, op.GetStrVal())); } uacon = UsualArithmeticConversions(lop, rop); lop = uacon.first; rop = uacon.last; res.type = lop.GetType(); break; case Token.Type.OP_ASSIGN: if (!lop.IsLvalue()) { throw new Symbols.Exception(lop, NOT_LVALUE); } if (!lt.Equals(rt)) { rop = new Cast(rop, lt); } res.type = lop.GetType(); break; case Token.Type.COMMA: break; case Token.Type.OP_MUL_ASSIGN: case Token.Type.OP_DIV_ASSIGN: case Token.Type.OP_MOD_ASSIGN: case Token.Type.OP_PLUS_ASSIGN: case Token.Type.OP_SUB_ASSIGN: case Token.Type.OP_L_SHIFT_ASSIGN: case Token.Type.OP_R_SHIFT_ASSIGN: case Token.Type.OP_BIT_AND_ASSIGN: case Token.Type.OP_BIT_OR_ASSIGN: case Token.Type.OP_XOR_ASSIGN: Token.Type tt = Token.Type.OP_STAR; switch (op.type) { case Token.Type.OP_MUL_ASSIGN: tt = Token.Type.OP_STAR; break; case Token.Type.OP_DIV_ASSIGN: tt = Token.Type.OP_DIV; break; case Token.Type.OP_MOD_ASSIGN: tt = Token.Type.OP_MOD; break; case Token.Type.OP_PLUS_ASSIGN: tt = Token.Type.OP_PLUS; break; case Token.Type.OP_SUB_ASSIGN: tt = Token.Type.OP_SUB; break; case Token.Type.OP_L_SHIFT_ASSIGN: tt = Token.Type.OP_L_SHIFT; break; case Token.Type.OP_R_SHIFT_ASSIGN: tt = Token.Type.OP_R_SHIFT; break; case Token.Type.OP_BIT_AND_ASSIGN: tt = Token.Type.OP_BIT_AND; break; case Token.Type.OP_BIT_OR_ASSIGN: tt = Token.Type.OP_BIT_OR; break; case Token.Type.OP_XOR_ASSIGN: tt = Token.Type.OP_XOR; break; } BinaryOperator bop = new BinaryOperator(new Token(tt)); bop.SetLeftOperand(lop); bop.SetRightOperand(rop); res.op = new Token(op.GetIndex(), op.GetLine(), Token.Type.OP_ASSIGN, "="); BinaryOperator assign = new BinaryOperator(res.op); assign.SetLeftOperand(lop); assign.SetRightOperand(bop); BinaryConvertResult r = ConvertBinaryOperands(lop, bop, res.op); rop = r.right; lop = r.left; res.type = lop.GetType(); break; default: throw new System.NotImplementedException(); } res.left = lop; res.right = rop; return(res); }
public OptParam(Word name, Symbols.Type type, Constant defVal) : base(name, type) { DefaultValue = defVal; }