DavidNorgren

Untitled

Jan 11th, 2016
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 20.50 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.Windows.Forms;
  7.  
  8. namespace lab3 {
  9.  
  10.     // AST node
  11.  
  12.     class ASTobject {
  13.         public int line;
  14.         public ASTobject(int line) {
  15.             this.line = line;
  16.         }
  17.         public virtual TreeNode createTree() { return new TreeNode("Not implemented"); }
  18.         public virtual TokenType typeCheck(TypeChecker t) { return TokenType.ERROR; }
  19.         public virtual void generateCode(CodeGenerator g) { return; }
  20.     }
  21.  
  22.     // Statement list
  23.  
  24.     class ASTstmtList : ASTstmt {  
  25.         public List<ASTstmt> list = new List<ASTstmt>();
  26.         public VariableEnvironment env = new VariableEnvironment();
  27.  
  28.  
  29.         public ASTstmtList(int line) : base(null, line) { }
  30.  
  31.         public override TreeNode createTree() {
  32.             TreeNode n = new TreeNode("Statement list");
  33.             foreach (ASTstmt s in list)
  34.                 n.Nodes.Add(s.createTree());
  35.             return n;
  36.         }
  37.  
  38.         public override TokenType typeCheck(TypeChecker t) {
  39.  
  40.             // New environment
  41.             env = t.addEnvironment();
  42.  
  43.             // Check statements
  44.             foreach (ASTstmt s in list)
  45.                 s.typeCheck(t);
  46.  
  47.             // Leave environment
  48.             t.exitEnvironment();
  49.  
  50.             return TokenType.NOPE;
  51.         }
  52.  
  53.         public override void generateCode(CodeGenerator g) {
  54.             g.curEnv = env;
  55.             g.t.addEnvironment();
  56.  
  57.             foreach (ASTstmt s in list)
  58.                 s.generateCode(g);
  59.  
  60.             //Assumes all local variables are integers.
  61.             if (g.t.environments[g.t.environments.Count - 1].var.Count > 0)
  62.                 g.code.Add("POP " + g.t.environments[g.t.environments.Count - 1].var.Count);
  63.  
  64.             g.t.exitEnvironment();
  65.         }
  66.     }
  67.  
  68.     // Statement
  69.  
  70.     class ASTstmt : ASTobject {
  71.         public ASTexpr expr;
  72.  
  73.         public ASTstmt(ASTexpr expr, int line) : base(line) {
  74.             this.expr = expr;
  75.         }
  76.  
  77.         public override TreeNode createTree() {
  78.             TreeNode n = new TreeNode("Expression statement");
  79.             n.Nodes.Add(expr.createTree());
  80.             return n;
  81.         }
  82.  
  83.         public override TokenType typeCheck(TypeChecker t) {
  84.             return expr.typeCheck(t);
  85.         }
  86.  
  87.         public override void generateCode(CodeGenerator g) {
  88.             expr.generateCode(g);
  89.         }
  90.  
  91.     }
  92.  
  93.     // Return statement
  94.  
  95.     class ASTstmtReturn : ASTstmt {
  96.         public ASTstmtReturn(ASTexpr expr, int line) : base(expr, line) {
  97.             this.expr = expr;
  98.         }
  99.  
  100.         public override TreeNode createTree() {
  101.             TreeNode n = new TreeNode("Return statement");
  102.             if (expr != null)
  103.                 n.Nodes.Add(expr.createTree());
  104.             return n;
  105.         }
  106.  
  107.         public override TokenType typeCheck(TypeChecker t) {
  108.  
  109.             ASTstmtFuncDecl func = t.getCurrentFunction();
  110.  
  111.             // No function?
  112.             if (func == null)
  113.                 throw new Exception("Return without a function at line " + line);
  114.  
  115.             // If there's an expression, check if it's the same type as the function
  116.             if (expr != null) {
  117.                 if (expr.typeCheck(t) != func.dataType)
  118.                     throw new Exception("Invalid return type at line " + line);
  119.             } else if (func.dataType != TokenType.VOID) // If no expression, check if function is a void
  120.                 throw new Exception("Invalid return type at line " + line);
  121.  
  122.             // Store the return type in the typechecker, this is used at the end of FuncDecl
  123.             t.returnType = func.dataType;
  124.  
  125.             return t.returnType;
  126.         }
  127.  
  128.         public override void generateCode(CodeGenerator g) {
  129.             if (expr != null) {
  130.                 g.code.Add("LVAL " + (g.curParEnv.var.Count+2) + "(FP)");
  131.                 expr.generateCode(g);
  132.                 //Assumes int return value
  133.                 g.code.Add("ASSINT");
  134.             }
  135.         }
  136.     }
  137.  
  138.     // Write statement
  139.  
  140.     class ASTstmtWrite : ASTstmt {
  141.         public ASTstmtWrite(ASTexpr expr, int line) : base(expr, line) {
  142.             this.expr = expr;
  143.         }
  144.  
  145.         public override TreeNode createTree() {
  146.             TreeNode n = new TreeNode("Write call");
  147.             n.Nodes.Add(expr.createTree());
  148.             return n;
  149.         }
  150.  
  151.         public override TokenType typeCheck(TypeChecker t) {
  152.             if (expr.typeCheck(t) != TokenType.INT)
  153.                 throw new Exception("Invalid expression type for Write statement at line " + line);
  154.  
  155.             return TokenType.NOPE;
  156.         }
  157.  
  158.         public override void generateCode(CodeGenerator g) {
  159.             expr.generateCode(g);
  160.             g.code.Add("WRITEINT");
  161.             g.code.Add("POP 1");
  162.         }
  163.     }
  164.  
  165.     // Read statement
  166.  
  167.     class ASTstmtRead : ASTstmt {
  168.         public ASTstmtRead(ASTexpr expr, int line) : base(expr, line) {
  169.             this.expr = expr;
  170.         }
  171.  
  172.         public override TreeNode createTree() {
  173.             TreeNode n = new TreeNode("Read call");
  174.             n.Nodes.Add(expr.createTree());
  175.             return n;
  176.         }
  177.  
  178.         public override TokenType typeCheck(TypeChecker t) {
  179.             if (expr.typeCheck(t) != TokenType.INT)
  180.                 throw new Exception("Invalid expression type for Read statement at line " + line);
  181.  
  182.             return TokenType.NOPE;
  183.         }
  184.  
  185.         public override void generateCode(CodeGenerator g) {
  186.             g.isAss = true;
  187.             expr.generateCode(g);
  188.             g.code.Add("READINT");
  189.             g.code.Add("ASSINT");
  190.         }
  191.     }
  192.  
  193.     // Variable declaration
  194.  
  195.     class ASTstmtVarDecl : ASTstmt {
  196.         public TokenType dataType;
  197.         public ASTid id;
  198.  
  199.         public ASTstmtVarDecl(TokenType dataType, ASTid id, ASTexpr expr, int line) : base(expr, line) {
  200.             this.dataType = dataType;
  201.             this.id = id;
  202.             this.expr = expr;
  203.         }
  204.  
  205.         public override TreeNode createTree() {
  206.             TreeNode n = new TreeNode("Declare variable " + id.name);
  207.             if (expr != null)
  208.                 n.Nodes.Add(expr.createTree());
  209.             return n;
  210.         }
  211.  
  212.         public override TokenType typeCheck(TypeChecker t) {
  213.  
  214.             // We can't have void variables
  215.             if (dataType == TokenType.VOID)
  216.                 throw new Exception("Invalid variable type at line " + line);
  217.  
  218.             // Variable already exists?
  219.             if (!t.declareVariable(id.name, dataType))
  220.                 throw new Exception("Variable redefinition at line " + line);
  221.  
  222.             // A function with this name exists?
  223.             if (t.findFunction(id.name))
  224.                 throw new Exception("Variable declaration with same name as a function at line " + line);
  225.  
  226.             // The given expression is the same type?
  227.             if (expr != null && expr.typeCheck(t) != dataType)
  228.                 throw new Exception("Invalid initialization value");
  229.  
  230.             return TokenType.NOPE;
  231.  
  232.         }
  233.  
  234.         public override void generateCode(CodeGenerator g) {
  235.             bool success = g.t.declareVariable(id.name, dataType);
  236.            
  237.             if(success) {
  238.                 g.declareVar(dataType);
  239.  
  240.                 if (expr != null) {
  241.                     g.code.Add("LVAL -1(FP)");
  242.                     expr.generateCode(g);
  243.                     if (dataType == TokenType.INT)
  244.                         g.code.Add("ASSINT");
  245.                 }
  246.             }
  247.         }
  248.     }
  249.  
  250.     // Function declaration
  251.  
  252.     class ASTstmtFuncDecl : ASTstmt {
  253.         public TokenType dataType;
  254.         public ASTid id;
  255.         public ASTparList parList;
  256.         public ASTstmtList stmtList;
  257.         public VariableEnvironment parEnv;
  258.  
  259.         public ASTstmtFuncDecl(TokenType dataType, ASTid id, ASTparList parList, ASTstmtList stmtList, int line) : base(null, line) {
  260.             this.dataType = dataType;
  261.             this.id = id;
  262.             this.parList = parList;
  263.             this.stmtList = stmtList;
  264.         }
  265.  
  266.         public override TreeNode createTree() {
  267.             TreeNode n = new TreeNode("Declare " + dataType + " function " + id.name);
  268.             TreeNode np = n.Nodes.Add("Parameters");
  269.             foreach (ASTpar p in parList.list)
  270.                 np.Nodes.Add(p.createTree());
  271.             n.Nodes.Add(stmtList.createTree());
  272.             return n;
  273.         }
  274.  
  275.         public override TokenType typeCheck(TypeChecker t) {
  276.  
  277.             // Add function to typechecker list
  278.             if (!t.declareFunction(this))
  279.                 throw new Exception("Function redeclaration at line " + line);
  280.  
  281.             // Add parameters to new scope
  282.             parEnv = t.addEnvironment();
  283.             foreach (ASTpar p in parList.list) {
  284.                 if (t.findFunction(p.id.name))
  285.                     throw new Exception("Parameter with same name as a function at line " + line);
  286.                 if (!t.declareVariable(p.id.name, p.dataType))
  287.                     throw new Exception("Parameter redefinition at line " + line);
  288.             }
  289.  
  290.             // Check statement list
  291.             stmtList.typeCheck(t);
  292.  
  293.             // Check return type (fetched from a return statement inside the list)
  294.             if (t.returnType != dataType)
  295.                 throw new Exception("Missing return for function at line " + line);
  296.  
  297.             t.exitEnvironment();
  298.  
  299.             return dataType;
  300.         }
  301.  
  302.         public override void generateCode(CodeGenerator g) {
  303.            
  304.             g.code.Add("[" + id.name + "]");
  305.  
  306.             g.code.Add("LINK");
  307.            
  308.             g.curParEnv = parEnv;
  309.  
  310.             /*
  311.             foreach (ASTpar p in parList.list)
  312.                 p.generateCode(g);
  313.             */
  314.             stmtList.generateCode(g);
  315.  
  316.  
  317.             g.code.Add("UNLINK");
  318.             g.code.Add("RTS");
  319.  
  320.         }
  321.     }
  322.  
  323.     // If statement
  324.  
  325.     class ASTstmtIf : ASTstmt {
  326.         ASTstmt stmt, stmtElse;
  327.         public ASTstmtIf(ASTexpr expr, ASTstmt stmt, ASTstmt stmtElse, int line) : base(expr, line) {
  328.             this.stmt = stmt;
  329.             this.stmtElse = stmtElse;
  330.         }
  331.  
  332.         public override TreeNode createTree() {
  333.             TreeNode n = new TreeNode("If statement");
  334.             n.Nodes.Add("Condition").Nodes.Add(expr.createTree());
  335.             n.Nodes.Add(stmt.createTree());
  336.             if (stmtElse != null)
  337.                 n.Nodes.Add("Else").Nodes.Add(stmtElse.createTree());
  338.             return n;
  339.         }
  340.  
  341.         public override TokenType typeCheck(TypeChecker t) {
  342.  
  343.             // Check expression
  344.             if (expr.typeCheck(t) != TokenType.INT)
  345.                 throw new Exception("Invalid expression type for If statement at line " + line);
  346.  
  347.             // Check statements
  348.             stmt.typeCheck(t);
  349.             if (stmtElse != null)
  350.                 stmtElse.typeCheck(t);
  351.  
  352.             return TokenType.NOPE;
  353.  
  354.         }
  355.  
  356.         public override void generateCode(CodeGenerator g) {
  357.            
  358.             //start label
  359.             g.code.Add("[" + g.labelCounter + "if]");
  360.            
  361.             // evaluate conditional and skip statement body if it's false
  362.             expr.generateCode(g);
  363.             g.code.Add("BRF " + g.labelCounter + "elseif");
  364.  
  365.             //Statement body, if this part is reached the statement was true and the else statement should be skipped.
  366.             stmt.generateCode(g);
  367.             g.code.Add("BRA " + g.labelCounter + "endif");
  368.  
  369.             g.code.Add("[" + g.labelCounter + "elseif]");
  370.  
  371.             if (stmtElse != null)
  372.                 stmtElse.generateCode(g);
  373.  
  374.             g.code.Add("[" + g.labelCounter + "endif]");
  375.  
  376.             g.labelCounter++;
  377.         }
  378.     }
  379.  
  380.     // While statement
  381.  
  382.     class ASTstmtWhile : ASTstmt {
  383.         ASTstmt stmt;
  384.         public ASTstmtWhile(ASTexpr expr, ASTstmt stmt, int line) : base(expr, line) {
  385.             this.stmt = stmt;
  386.         }
  387.  
  388.         public override TreeNode createTree() {
  389.             TreeNode n = new TreeNode("While statement");
  390.             n.Nodes.Add("Condition").Nodes.Add(expr.createTree());
  391.             n.Nodes.Add(stmt.createTree());
  392.             return n;
  393.         }
  394.  
  395.         public override TokenType typeCheck(TypeChecker t) {
  396.  
  397.             // Check expression
  398.             if (expr.typeCheck(t) != TokenType.INT)
  399.                 throw new Exception("Invalid expression type for While statement at line " + line);
  400.  
  401.             // Check statement
  402.             stmt.typeCheck(t);
  403.  
  404.             return TokenType.NOPE;
  405.         }
  406.  
  407.         public override void generateCode(CodeGenerator g) {
  408.             //start Label
  409.             g.code.Add("[" + g.labelCounter + "while]");
  410.  
  411.             // evaluate conditional and skip statement body if it's false
  412.             expr.generateCode(g);
  413.             g.code.Add("BRF " + g.labelCounter + "endwhile");
  414.  
  415.             stmt.generateCode(g);
  416.             g.code.Add("BRA " + g.labelCounter + "while");
  417.  
  418.             g.code.Add("[" + g.labelCounter + "endwhile]");
  419.  
  420.         }
  421.     }
  422.  
  423.     // Function parameter list
  424.  
  425.     class ASTparList : ASTobject {
  426.         public ASTparList(int line) : base(line) { }
  427.         public List<ASTpar> list = new List<ASTpar>();
  428.     }
  429.  
  430.     // Function parameter
  431.  
  432.     class ASTpar : ASTobject {
  433.         public TokenType dataType;
  434.         public ASTid id;
  435.  
  436.         public ASTpar(TokenType type, ASTid id, int line) : base(line) {
  437.             this.dataType = type;
  438.             this.id = id;
  439.         }
  440.         public override TreeNode createTree() {
  441.             return new TreeNode(dataType + " " + id.name);
  442.         }
  443.  
  444.         public override void generateCode(CodeGenerator g) {
  445.             return;
  446.         }
  447.     }
  448.  
  449.     // Function argument list
  450.  
  451.     class ASTargList : ASTobject {
  452.         public ASTargList(int line) : base(line) { }
  453.         public List<ASTexpr> list = new List<ASTexpr>();
  454.     }
  455.  
  456.     // Number
  457.  
  458.     class ASTint : ASTobject {
  459.         int value;
  460.  
  461.         public ASTint(int value, int line) : base(line) {
  462.             this.value = value;
  463.         }
  464.  
  465.         public override TreeNode createTree() {
  466.             return new TreeNode("INT: " + value);
  467.         }
  468.  
  469.         public override TokenType typeCheck(TypeChecker t) {
  470.             return TokenType.INT;
  471.         }
  472.  
  473.         public override void generateCode(CodeGenerator g) {
  474.             g.PushInt(value);
  475.         }
  476.     }
  477.  
  478.     // ID
  479.  
  480.     class ASTid : ASTobject {
  481.         public string name;
  482.         public TokenType dataType;
  483.  
  484.         public ASTid(string name, int line) : base(line) {
  485.             this.name = name;
  486.         }
  487.  
  488.         public override TreeNode createTree() {
  489.             return new TreeNode("ID: " + name);
  490.         }
  491.  
  492.         public override TokenType typeCheck(TypeChecker t) {
  493.             dataType = t.getVariable(name);
  494.  
  495.             if (dataType == TokenType.NOPE)
  496.                 throw new Exception("Undefined variable " + name + " at line " + line);
  497.            
  498.             return dataType;
  499.         }
  500.  
  501.         public override void generateCode(CodeGenerator g) {
  502.  
  503.             int i;
  504.             VariableEnvironment iter = g.curEnv;
  505.             string tracOP;
  506.  
  507.             if (g.isAss == true) {
  508.                 tracOP = "LVAL ";
  509.                 g.isAss = false;
  510.             }
  511.             else
  512.                 tracOP = "RVALINT ";
  513.  
  514.             for (i = g.curParEnv.var.Count; i > 0; i-- ) {
  515.                 if (g.curParEnv.var[i-1].name.Equals(name)) {
  516.                     g.code.Add(tracOP + (g.curParEnv.var[i-1].offset+1) + "(FP)");
  517.                     return;
  518.                 }
  519.             }
  520.  
  521.             while (iter != null) {
  522.                 foreach(Variable v in iter.var) {
  523.                     if(v.name.Equals(name)) {
  524.                         g.code.Add(tracOP + (v.offset * -1) + "(FP)");
  525.                         iter = null;
  526.                         return;
  527.                     }
  528.                 }
  529.                 iter = iter.prev;
  530.             }
  531.         }
  532.     }
  533.  
  534.     // Expression
  535.  
  536.     class ASTexpr : ASTobject {
  537.         TokenType op;
  538.         TokenType returnType;
  539.         ASTexpr left;
  540.         ASTexpr right;
  541.  
  542.         public ASTexpr(TokenType op, ASTexpr left, ASTexpr right, int line) : base(line) {
  543.             this.op = op;
  544.             this.left = left;
  545.             this.right = right;
  546.         }
  547.  
  548.         public override TreeNode createTree() {
  549.             TreeNode n = new TreeNode("Expr " + op);
  550.             if (left != null)
  551.                 n.Nodes.Add(left.createTree());
  552.             if (right != null)
  553.                 n.Nodes.Add(right.createTree());
  554.             return n;
  555.         }
  556.  
  557.         public override TokenType typeCheck(TypeChecker t) {
  558.  
  559.             if (op == TokenType.NOTOP) { // Unary
  560.                 TokenType rt = right.typeCheck(t);
  561.  
  562.                 // Right side (next to !) can't be void
  563.                 if (rt == TokenType.VOID)
  564.                     throw new Exception("Invalid type for operation " + op + " at line " + line);
  565.  
  566.                 return rt;
  567.             } else {
  568.                 TokenType lt, rt;
  569.                 lt = left.typeCheck(t);
  570.                 rt = right.typeCheck(t);
  571.  
  572.                 // Left and right side must be equal and not void
  573.                 if (lt == TokenType.VOID || rt == TokenType.VOID || lt != rt)
  574.                     throw new Exception("Invalid type for operation " + op + " at line " + line);
  575.  
  576.                 returnType = lt;
  577.                 return lt;
  578.             }
  579.         }
  580.  
  581.         public override void generateCode(CodeGenerator g) {
  582.  
  583.             //TODO
  584.             if (op == TokenType.NOTOP) { //Unary
  585.                 right.generateCode(g);
  586.                 g.Unary(op);
  587.                 return;
  588.             }
  589.            
  590.  
  591.             if( returnType == TokenType.INT) {
  592.                 if (op == TokenType.ASSOP)
  593.                     g.isAss = true;
  594.  
  595.                 left.generateCode(g);
  596.                 right.generateCode(g);
  597.                 g.IntOP(op);
  598.             }
  599.  
  600.         }
  601.     }
  602.  
  603.     // Expression value
  604.  
  605.     class ASTexprValue : ASTexpr {
  606.         ASTobject value;
  607.  
  608.         public ASTexprValue(ASTobject value, int line) : base(0, null, null, line) {
  609.             this.value = value;
  610.         }
  611.  
  612.         public override TreeNode createTree() {
  613.             return value.createTree();
  614.         }
  615.  
  616.         public override TokenType typeCheck(TypeChecker t) {
  617.             return value.typeCheck(t);
  618.         }
  619.  
  620.         public override void generateCode(CodeGenerator g) {
  621.             value.generateCode(g);
  622.         }
  623.     }
  624.  
  625.     // Expression function call
  626.  
  627.     class ASTexprCall : ASTexpr {
  628.         public ASTid id;
  629.         public ASTargList list;
  630.  
  631.         public ASTexprCall(ASTid id, ASTargList list, int line) : base(0, null, null, line) {
  632.             this.id = id;
  633.             this.list = list;
  634.         }
  635.  
  636.         public override TreeNode createTree() {
  637.             TreeNode n = new TreeNode("Call to function " + id.name);
  638.             foreach (ASTexpr e in list.list)
  639.                 n.Nodes.Add(e.createTree());
  640.             return n;
  641.         }
  642.  
  643.         public override TokenType typeCheck(TypeChecker t) {
  644.  
  645.             ASTstmtFuncDecl func = t.getFunction(id.name);
  646.  
  647.             // Check if function exists
  648.             if (func == null)
  649.                 throw new Exception("Call to undefined function " + id.name + " at line " + line);
  650.  
  651.             // Check argument count
  652.             if (list.list.Count != func.parList.list.Count)
  653.                 throw new Exception("Invalid argument count for function " + id.name + " at line " + line);
  654.  
  655.             // Check argument types
  656.             for (int a = 0; a < list.list.Count; a++)
  657.                 if (func.parList.list[a].dataType != list.list[a].typeCheck(t))
  658.                     throw new Exception("Invalid type for argument " + (a + 1) + " in call to function " + id.name + " at line " + line);
  659.  
  660.             return func.dataType;
  661.  
  662.         }
  663.  
  664.         public override void generateCode(CodeGenerator g) {
  665.             ASTstmtFuncDecl func = g.t.getFunction(id.name);
  666.  
  667.             if (func.dataType == TokenType.INT)
  668.                 g.code.Add("DECL 1");
  669.  
  670.             foreach (ASTexpr arg in list.list) {
  671.                 arg.generateCode(g);
  672.             }
  673.            
  674.             g.code.Add("BSR " + func.id.name);
  675.             if(list.list.Count > 0)
  676.                 g.code.Add("POP " + list.list.Count);
  677.         }
  678.     }
  679. }
Advertisement
Add Comment
Please, Sign In to add comment