├── .gitignore ├── README.md ├── Tutorial.md ├── Yx.iml ├── src ├── AST │ ├── ASTNode.java │ ├── ASTVisitor.java │ ├── ExprNode.java │ ├── FnRootNode.java │ ├── RootNode.java │ ├── StmtNode.java │ ├── assignExprNode.java │ ├── binaryExprNode.java │ ├── blockStmtNode.java │ ├── cmpExprNode.java │ ├── constExprNode.java │ ├── exprStmtNode.java │ ├── ifStmtNode.java │ ├── returnStmtNode.java │ ├── structDefNode.java │ ├── varDefStmtNode.java │ └── varExprNode.java ├── Assembly │ ├── AsmBlock.java │ ├── AsmFn.java │ ├── Inst │ │ ├── Bz.java │ │ ├── IType.java │ │ ├── Inst.java │ │ ├── Jp.java │ │ ├── Ld.java │ │ ├── Li.java │ │ ├── Mv.java │ │ ├── RType.java │ │ ├── Ret.java │ │ └── St.java │ └── Operand │ │ ├── Imm.java │ │ ├── Operand.java │ │ ├── PhyReg.java │ │ ├── Reg.java │ │ └── VirtualReg.java ├── Backend │ ├── AsmPrinter.java │ ├── IRBuilder.java │ ├── IRPrinter.java │ ├── InstSelector.java │ ├── Pass.java │ └── RegAlloc.java ├── Frontend │ ├── ASTBuilder.java │ ├── SemanticChecker.java │ └── SymbolCollector.java ├── MIR │ ├── binary.java │ ├── block.java │ ├── branch.java │ ├── constant.java │ ├── entity.java │ ├── jump.java │ ├── mainFn.java │ ├── register.java │ ├── ret.java │ ├── statement.java │ └── terminalStmt.java ├── Main.java ├── Parser │ ├── Yx.g4 │ ├── Yx.interp │ ├── Yx.tokens │ ├── YxBaseListener.java │ ├── YxBaseVisitor.java │ ├── YxLexer.interp │ ├── YxLexer.java │ ├── YxLexer.tokens │ ├── YxListener.java │ ├── YxParser.java │ └── YxVisitor.java └── Util │ ├── Scope.java │ ├── Type.java │ ├── YxErrorListener.java │ ├── error │ ├── error.java │ ├── internalError.java │ ├── semanticError.java │ └── syntaxError.java │ ├── globalScope.java │ └── position.java └── testcases ├── correct.yx ├── wrong1 - int not match.yx ├── wrong2 - bool not match.yx ├── wrong3 - variable undefined.yx └── wrong4 - multi definition.yx /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | 25 | .idea/ 26 | /test.yx 27 | /out/ 28 | /output.s 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Yx 2 | This is a language only for demo use. 3 | 4 | #### Grammar 5 | 6 | ##### Type 7 | 8 | It has `int` and `bool` type in default(but no bool variable) 9 | 10 | It also support definition of struct 11 | 12 | ##### Arithmetic operation 13 | 14 | arithmetic operation can only be '+', '-' or '==', '!='. 15 | 16 | ##### Statement 17 | 18 | A statement can only be: 19 | 20 | 1. a definition of a variable 21 | 2. an expression 22 | 3. an 'if-else' 23 | 4. a return -------------------------------------------------------------------------------- /Tutorial.md: -------------------------------------------------------------------------------- 1 | Yx: a simplified smallest grammar. 2 | 3 | ### Grammar 4 | 5 | ##### Type 6 | 7 | It has int and bool type as default(but no bool variable) 8 | 9 | It also supports definition of struct just in the way of C++. But ignore this line at first(until [Intro to type](#Brief introduction to type)). 10 | 11 | ##### Arithmetic operation 12 | 13 | arithmetic operation can only be '+', '-' or '==', '!='. 14 | 15 | ##### Statement 16 | 17 | A statement can only be: 18 | 19 | 1. a definition of a variable 20 | 2. an expression 21 | 3. `if`-`else` statement 22 | 4. `return` 23 | 24 | ### Implementation of Naïve Front-End 25 | 26 | #### Write the grammar 27 | 28 | A native order is: 29 | 30 | program - statement - expression - primary 31 | 32 | In Mx, function and class definition is between program and statement. 33 | 34 | The grammar of '.g4' file is known. Only few parts to mention: 35 | 36 | 1. use of `#` 37 | 2. use of `` 38 | 39 | ```Antlr4 40 | grammar Yx; 41 | 42 | program: 'int main()' suite EOF; 43 | 44 | varDef : Int Identifier ('=' expression)? ';'; 45 | 46 | suite : '{' statement* '}'; 47 | 48 | statement 49 | : suite #block 50 | | varDef #vardefStmt 51 | | If '(' expression ')' trueStmt=statement 52 | (Else falseStmt=statement)? #ifStmt 53 | | Return expression? ';' #returnStmt 54 | | expression ';' #pureExprStmt 55 | | ';' #emptyStmt 56 | ; 57 | 58 | expression 59 | : primary #atomExpr 60 | | expression op=('+' | '-') expression #binaryExpr 61 | | expression op=('==' | '!=' ) expression #binaryExpr 62 | | expression '=' expression #assignExpr 63 | ; 64 | 65 | primary 66 | : '(' expression ')' 67 | | Identifier 68 | | literal 69 | ; 70 | 71 | literal 72 | : DecimalInteger 73 | ; 74 | 75 | Int : 'int'; 76 | If : 'if'; 77 | Else : 'else'; 78 | Return : 'return'; 79 | 80 | LeftParen : '('; 81 | RightParen : ')'; 82 | LeftBracket : '['; 83 | RightBracket : ']'; 84 | LeftBrace : '{'; 85 | RightBrace : '}'; 86 | 87 | Less : '<'; 88 | LessEqual : '<='; 89 | Greater : '>'; 90 | GreaterEqual : '>='; 91 | LeftShift : '<<'; 92 | RightShift : '>>'; 93 | 94 | Plus : '+'; 95 | Minus : '-'; 96 | 97 | And : '&'; 98 | Or : '|'; 99 | AndAnd : '&&'; 100 | OrOr : '||'; 101 | Caret : '^'; 102 | Not : '!'; 103 | Tilde : '~'; 104 | 105 | Question : '?'; 106 | Colon : ':'; 107 | Semi : ';'; 108 | Comma : ','; 109 | 110 | Assign : '='; 111 | Equal : '=='; 112 | NotEqual : '!='; 113 | 114 | Identifier 115 | : [a-zA-Z] [a-zA-Z_0-9]* 116 | ; 117 | 118 | DecimalInteger 119 | : [1-9] [0-9]* 120 | | '0' 121 | ; 122 | 123 | Whitespace 124 | : [ \t]+ 125 | -> skip 126 | ; 127 | 128 | Newline 129 | : ( '\r' '\n'? 130 | | '\n' 131 | ) 132 | -> skip 133 | ; 134 | 135 | BlockComment 136 | : '/*' .*? '*/' 137 | -> skip 138 | ; 139 | 140 | LineComment 141 | : '//' ~[\r\n]* 142 | -> skip 143 | ; 144 | ``` 145 | 146 | #### The Parse Part in compiler 147 | 148 | Build `YxLexer.java` and `YxParser.java` by ANTLR4. 149 | 150 | Then use them in main: 151 | 152 | ```java 153 | public static void main(String[] args) throws Exception{ 154 | String name = "test.yx"; 155 | InputStream input = new FileInputStream(name); 156 | try { 157 | YxLexer lexer = new YxLexer(CharStreams.fromStream(input)); 158 | lexer.removeErrorListeners(); 159 | lexer.addErrorListener(new YxErrorListener()); 160 | YxParser parser = new YxParser(new CommonTokenStream(lexer)); 161 | parser.removeErrorListeners(); 162 | parser.addErrorListener(new YxErrorListener()); 163 | ParseTree parseTreeRoot = parser.program(); 164 | } catch (error er) { 165 | System.err.println(er.toString()); 166 | throw new RuntimeException(); 167 | } 168 | } 169 | ``` 170 | 171 | The `error` class is a trivial self-implemented error type. The `YxErrorListener` is defined as: 172 | 173 | ```java 174 | import org.antlr.v4.runtime.BaseErrorListener; 175 | import org.antlr.v4.runtime.RecognitionException; 176 | import org.antlr.v4.runtime.Recognizer; 177 | 178 | public class YxErrorListener extends BaseErrorListener { 179 | @Override 180 | public void syntaxError(Recognizer recognizer, 181 | Object offendingSymbol, 182 | int line, int charPositionInLine, 183 | String msg, 184 | RecognitionException e) { 185 | 186 | throw new syntaxError(msg, new position(line, charPositionInLine)); 187 | } 188 | } 189 | ``` 190 | 191 | #### Design The AST 192 | 193 | Although the parsed program is tree-like, an AST is still required since each node should have some more value. It is designed as: 194 | 195 | ``` 196 | - ASTNode 197 | - RootNode // node as a root 198 | - StmtNode // node as a statement 199 | - varDefStmtNode 200 | - returnStmtNode 201 | - blockStmtNode 202 | - exprStmtNode 203 | - ifStmtNode 204 | - ExprNode // node as an expression 205 | - assignExprNode 206 | - binaryExprNode 207 | - constExprNode 208 | - cmpExprNode 209 | - varExprNode 210 | ``` 211 | 212 | As an example, the most naïve implementation of ifStmtNode is: 213 | 214 | ```java 215 | package AST; 216 | 217 | import Util.position; 218 | 219 | public class ifStmtNode extends StmtNode { 220 | ExprNode condition; 221 | StmtNode thenStmt, elseStmt; 222 | 223 | public ifStmtNode(ExprNode condition, StmtNode thenStmt, StmtNode elseStmt, position pos) { 224 | super(pos); 225 | this.condition = condition; 226 | this.thenStmt = thenStmt; 227 | this.elseStmt = elseStmt; 228 | } 229 | 230 | @Override 231 | public void accept(ASTVisitor visitor) { 232 | visitor.visit(this); 233 | } 234 | } 235 | ``` 236 | 237 | Notice that, the return value type of AST visitor can be any one rather than void. This is based on your own design. 238 | 239 | #### AST Builder 240 | 241 | Build the AST. The AST Builder is a visitor on the parse tree. 242 | 243 | This step is trivial. Here's an example: 244 | 245 | ```java 246 | @Override public ASTNode visitVarDef(YxParser.VarDefContext ctx) { 247 | String name = ctx.Identifier().toString(); 248 | ExprNode expr = null; 249 | if (ctx.expression() != null) expr = (ExprNode)visit(ctx.expression()); 250 | 251 | return new varDefStmtNode(name, expr, new position(ctx)); 252 | } 253 | ``` 254 | 255 | #### Scope 256 | 257 | In global scope, the type system is recorded. But in this language it is not required since we only have `int` and `bool`. 258 | 259 | Every scope records variables defined in it. 260 | 261 | ```java 262 | import Util.error.semanticError; 263 | import java.util.HashSet; 264 | 265 | public class Scope { 266 | 267 | private HashSet members; 268 | private Scope parentScope; 269 | 270 | 271 | public Scope(Scope parentScope) { 272 | members = new HashSet<>(); 273 | this.parentScope = parentScope; 274 | } 275 | 276 | public Scope parentScope() { 277 | return parentScope; 278 | } 279 | 280 | public void defineVariable(String name, position pos) { 281 | if (members.contains(name)) 282 | throw new semanticError("member redefine", pos); 283 | members.add(name); 284 | } 285 | 286 | public boolean containsVariable(String name, boolean lookUpon) { 287 | if (members.contains(name)) return true; 288 | else if (parentScope != null && lookUpon) return parentScope.containsMember(name, true); 289 | else return false; 290 | } 291 | } 292 | ``` 293 | 294 | #### Semantic 295 | 296 | Now we can do the semantic check. In Yx, We need to consider: 297 | 298 | 1. If the type matches. 299 | 300 | So we introduce attribute `type` for each `ExprNode`. Luckily, in Yx the type of each ```ExprNode``` is known(`int` except for `cmpExprNode`). But in Mx, setting type in semantic check stage is required and in OOP language like C++, type infer is required. 301 | 302 | 2. Right-value at left. 303 | 304 | So we introduce `isAssignable` for each `ExprNode`. 305 | 306 | 3. undefined/multi-define variable. 307 | 308 | Is there anything more? In Mx there are of course more to consider, and maybe some more AST visitors are required to do preprocess. 309 | 310 | A fragment of the semantic checker is like: 311 | 312 | ```java 313 | @Override 314 | public void visit(varDefStmtNode it) { 315 | if (it.init != null) { 316 | it.init.accept(this); 317 | if (!it.init.type.isInt) 318 | throw new semanticError("Semantic Error: type not match.", 319 | it.init.pos); 320 | } 321 | currentScope.defineVariable(it.name, it.pos); 322 | } 323 | ``` 324 | 325 | Mention that the order is important. In the above example, if we define the variable at the beginning of the function, the case below can not be detected: 326 | 327 | ``` 328 | int x = x + 1; 329 | ``` 330 | 331 | So you'd better be very careful. 332 | 333 | #### Brief introduction to type 334 | 335 | To explain how to do semantic check with type, we introduce the following grammar: 336 | 337 | ```Antlr4 338 | classDef : 'struct' Identifier '{' varDef* '}'';'; 339 | ``` 340 | 341 | We also modify `varDef` and `program`: 342 | 343 | ```Antlr4 344 | program: classDef* mainFn; 345 | 346 | mainFn: 'int' 'main()' suite EOF; // original program 347 | 348 | varDef : type Identifier ('=' expression)? ';'; 349 | type : Int | Identifier; 350 | ``` 351 | 352 | You can easily add the corresponding `ASTNode` if you read the prior part carefully. So we skip the work. Assume `fnNode`(corresponding to `mainFn`) and `classDefNode` are implemented. 353 | 354 | We now face a problem: how to deal with: 355 | 356 | ``` 357 | struct a{ 358 | b x; 359 | }; 360 | struct b{ 361 | a x; 362 | }; 363 | ``` 364 | 365 | Of course, this is not a good design in C/C++ since you can have x.x.x...... However, in Mx and Yx, all variables are in form of reference, so we can have: 366 | 367 | ```java 368 | a y; 369 | y.x = null; 370 | ``` 371 | 372 | And the design above is good. 373 | 374 | What is the problem? If you check the correctness of `struct a`, you do not know if `b` is a legal type, vise versa. 375 | 376 | To solve the problem, we use another pass named `SymbolCollector`, which briefly collects all type names into a global scope. A global scope is a class derived from `Scope` by adding a map to collect these types. See `Util/globalScope` for more details. 377 | 378 | ```java 379 | @Override public void visit(structDefNode it) { 380 | Type struct = new Type(); 381 | struct.members = new HashMap<>(); 382 | it.varDefs.forEach(vd -> vd.accept(this)); 383 | gScope.addType(it.name, struct, it.pos); 384 | } 385 | ``` 386 | 387 | After this pass, we already have the name of all available types. So we can check the type of members in a struct: 388 | 389 | ```java 390 | if (currentStruct != null) { 391 | assert (currentStruct.members != null); 392 | if (currentStruct.members.containsKey(it.name)) 393 | throw new semanticError("redefinition of member " + it.name, it.pos); 394 | currentStruct.members.put(it.name, gScope.getTypeFromName(it.typeName, it.pos)); 395 | if (it.init != null) 396 | throw new semanticError("Yx does not support default init of members", 397 | it.init.pos); 398 | } 399 | ``` 400 | 401 | Modifications above help check the definition of struct and variable. Then we modify original `Scope` to support variables **in experissions** with type not only `int`: 402 | 403 | ```java 404 | public Type getType(String name, boolean lookUpon) { 405 | if (members.containsKey(name)) return members.get(name); 406 | else if (parentScope != null && lookUpon) 407 | return parentScope.getType(name, true); 408 | return null; 409 | } 410 | ``` 411 | 412 | Now, as the type of `varExprNode` and `assignExprNode` can be not only `intType`, we slightly modify it by adding: 413 | ```java 414 | it.type = it.rhs.type 415 | ``` 416 | at the end of `visit(assignExprNode it)` and 417 | ```java 418 | it.type = currentScope.getType(it.name, true) 419 | ``` 420 | at the end of `visit(varExprNode it)`. 421 | 422 | ### Codegen 423 | 424 | welcome to the next stage! 425 | 426 | Now you have a abstract semantic tree passing semantic check. The next thing to do is to turn it into corresponding assembly code. Generally, you may think about how to turn AST into assembly code directly, but in fact, we have an intermediate stage named IR(Intermediate Representation). 427 | 428 | This is because both AST and assembly code is not convenient for us to do optimization. Hence, we design our own IR and the process of compiling is expected to be: 429 | 430 | ``` 431 | code ---> AST ---> IR ---> IR ... ---> IR ---> assembly 432 | frontend optimization backend 433 | ``` 434 | 435 | IR is a very personal design, and here we only provide an approach to design one: 436 | 437 | #### IR Design 438 | 439 | Consider why we do not use AST. For the case: 440 | 441 | ```C++ 442 | x = a + b + c + d; 443 | y = a + b + c + e; 444 | ``` 445 | 446 | The result of `a+b+c` can be only calculated once. This shows such a case: In two subtrees, some smaller parts are isomorphic. To detect the case, a pairwise comparison for each parts are required. 447 | 448 | This can be simplified to the following method: we pairwisely compare trees with a height in each iteration, and in the next iteration, compare trees exactly one higher. 449 | 450 | Notice that, actually we do the following: In the first iteration, `a+b` is the same subtree. Then we let `apb = a+b` and in the next iteration `a+b+c` is the same subtree, which can be turned to `apb+c`. If we use such `apb`, we can say that each iteration we actually do the same thing: compare trees with height of two. 451 | 452 | Here we notice a deeper fact: the tree structure is not essential in optimization. Instead, we only need expressions with only one operator and at most two operands. More complex expressions can be turned to this one by splitting them into parts. (**This conclusion is correct only for Yx**, although for Mx and languages like C++ it is almost sure correct) 453 | 454 | The idea as another advantage: in assemble code, we only have operations with two operands. 455 | 456 | By this idea, our IR is designed to have grammar: 457 | 458 | ``` 459 | x = u op v; 460 | ``` 461 | 462 | where `x,u,v` are all constants, variables or intermediate result(for instance, `apb` in the case above). Or, to assume the program runs on a machine, we call them registers storing values of variables or intermediate results(abbreviated as registers). 463 | 464 | What about structs? As we only have assignments for structs, which is actually assignments of pointers, this is nothing different: register of a struct variable is the register storing the value of pointer of the struct variable. 465 | 466 | ​ What if we add a grammar to access the member of a struct? First get the pointer of the member using an offset, then introduce load/store instruction to get access to the value of the pointer. 467 | 468 | ​ What if we add a grammar to allocate and free the memory of the struct? Add a grammar in IR to call `malloc/free` method. 469 | 470 | What about `if-then`? Notice that by `a op b` operations, value of the boolean expression is stored in a register. So we can introduce branch instructions to deal with it: 471 | 472 | ``` 473 | br u label1, label2 474 | j label 475 | ``` 476 | 477 | The jump instruction is at the end of true branch and false branch to jump into the same place: the next statement after `if-else`. 478 | 479 | In all, we have grammars of IR: 480 | 481 | ``` 482 | x = u op v, (op = '+'/'-'/'=='/'!=') 483 | br u label1, label2 484 | j label 485 | ret u 486 | ``` 487 | 488 | The last thing is to define a block: it starts from a label and end at the first branch/jump instruction. The definition of block is important since it is a kind of CFG(control flow graph), and many optimizations are based on CFG, just like many optimizations are about binary operation. 489 | 490 | #### IR Builder 491 | 492 | We first define classes for IR grammars: registers, constants, blocks, three kinds of statements. Labels can be represented by blocks. 493 | 494 | Now you must have some knowledge of Java(or the language you use), so we skip the definition of these classes. 495 | 496 | As this is a very trivial one, we let the size of each register be 32bits(that is, a boolean intermediate result still has size of 32 bits) 497 | 498 | Now we have prepared everything for `IRBuilder`. Let's do it. Each `exprNode` in AST corresponds to a constant or a register, so we give `exprNode` a new member named `val`. Now we use this member to construct our IR: 499 | 500 | ```java 501 | @Override 502 | public void visit(cmpExprNode it) { 503 | it.lhs.accept(this); 504 | it.rhs.accept(this); 505 | register value = new register(); 506 | binary.opType op = it.opCode == cmpExprNode.cmpOpType.eq ? eq : ne; 507 | currentBlock.push_back(new binary(value, it.lhs.val, it.rhs.val, op)); 508 | it.val = value; 509 | } 510 | 511 | @Override 512 | public void visit(varExprNode it) { 513 | it.val = currentScope.getEntity(it.name, true); 514 | } 515 | ``` 516 | 517 | Other `exprNode` are handled likewise. 518 | 519 | The maintenance of `block` should also be mentioned: 520 | 521 | ```java 522 | @Override 523 | public void visit(ifStmtNode it) { 524 | it.condition.accept(this); 525 | block trueBranch = new block(), falseBranch = new block(); 526 | currentBlock.push_back(new branch(it.condition.val, trueBranch, falseBranch)); 527 | 528 | block destination = new block(); 529 | currentBlock = trueBranch; 530 | it.thenStmt.accept(this); 531 | currentBlock.push_back(new jump(destination)); 532 | currentBlock = falseBranch; 533 | it.elseStmt.accept(this); 534 | currentBlock.push_back(new jump(destination)); 535 | currentBlock = destination; 536 | } 537 | ``` 538 | 539 | ##### IR Printer 540 | 541 | To check the correctness of our IR, we can make an IR printer. Here we also introduce the concept of `Pass`. A `Pass` defines how to visit or modify a `program/function/block`, and in optimization stage, each kind of optimization can be regarded as a `Pass`. The program(or part of the program) passes a `Pass`, which may modify the passed part to do optimization or analyze the part for further optimization, and output the modified program. 542 | 543 | IR Printer is a very typical `Pass`. When the program passes the pass, each block is passed. When a block is passing, the `IRPrinter` pass prints each statement in order. 544 | 545 | For simplicity, we only have one kind of `Pass` in `Yx`, which visits the whole program(in `Yx` it equals the main function). 546 | 547 | ##### Prune 548 | 549 | It is meaningful to prune some cases in `IRBuilder` to release the pressure of later codegen stages. 550 | 551 | ##### Other kinds of IR 552 | 553 | The IR above can be identified as a graph IR. There is also tree IR very close to AST structure. You can even have a number of different IR, and lower the program from one IR to another. Each time you turn the program into a lower level of IR, there are some information discarded, just like what happens when you ignore the tree structure of AST and turn it into the graph IR. As a trade-off, you may get access to some information more easily. 554 | 555 | In all, design your own IR. 556 | 557 | #### Instruction selection 558 | 559 | Assume that the program is great-optimized in IR level. Now we turn IR into the assembly code. The first step is to select the correct instruction in assembly language. So we create a sets of classes to represent different assembly instructions. This is nothing different from the steps in IR language, and the pressure is released as our graph IR is very close to assembly code grammar. (So for tree IR, although in `IRBuilder` step there is not that much things, it should also consider a translation from tree shape to graph of blocks in the end.) 560 | 561 | Notice that, as the output is assembly code, we can have more freedom in this step: instructions like `mv`, `ret`, `li` are more readable. We should also notice that some native operations are not in RISCV assembly instructions. For instance, we do not have `seq` and `sne`, so we need to translate them to `sub`+`seqz/snez`. 562 | 563 | In this step, we still use virtual registers. That is, we assume that there are infinite registers although actually there are 32(actually less, due to the convention of `zero`, `sp`, `gp`, `tp `etc.). 564 | 565 | When you are at this stage, I believe you have enough knowledge to write your own instruction selection, since all you need is to be careful and consider all cases. 566 | 567 | ##### Asm Printer 568 | 569 | Although our registers are still virtual register, we implement the assembly code printer first, in order to help the process of debug for instruction selection. This is nothing different from the IR printer. 570 | 571 | #### Register Allocation 572 | 573 | This is the final step! We now focus on the problem that registers are limited in RISCV architecture. As the calling convention defines, some of them are caller-save, which means after calling a function, values in the register is not promised to be kept, while others are callee-save, which, in contrast, are kept the same after calling a function. We can also regarded them as caller-responsible and callee-responsible. 574 | 575 | The caller-save registers' liveness is at most from a function call to a function call, while the callee-save registers' liveness is at most cross the whole function. However, once you use such a register, you need to store its original value at the start of the function and restore before the return statement. 576 | 577 | You may think about recording what callee-save registers are used and then add corresponding store/load instructions after all. But there is a more typical way: you can simply add a virtual register for a callee-save physical register, and then add move instructions at the start and end of the function. If the register is not used, by coloring method, the move will be discarded in peephole optimization. 578 | 579 | Here we only talk about naïve register allocation, which uses at most three registers in a time: It stores all virtual registers - each corresponds to a variable/intermediate value - on the stack, loads when the value is required and stores when the value is modified. So we inserts a load for each used virtual register before an instruction and a store after an instruction. 580 | 581 | We want to consider less, so we use caller-save registers `t0`, `t1`, `t2`, whose indices are 5-7. 582 | 583 | For preparation, we introduce two command: `load` and `store`. For simplicity, all virtual registers are in size of 4B, so only `lw` and `sw` are used. 584 | 585 | ```java 586 | public class Ld extends Inst{ 587 | public PhyReg rd, addr; 588 | public Imm offset; 589 | 590 | public Ld(PhyReg rd, PhyReg addr, Imm offset) { 591 | this.rd = rd; 592 | this.addr = addr; 593 | this.offset = offset; 594 | } 595 | @Override 596 | public String toString() { 597 | return "lw " + rd + ", " + addr + "(" + offset + ")"; 598 | } 599 | } 600 | ``` 601 | 602 | ```java 603 | private Inst loadVirtualReg(VirtualReg r, PhyReg rd) { 604 | return new Ld(rd, sp, new Imm(r.index * 4)); 605 | } 606 | private Inst storeVirtualReg(VirtualReg r) { 607 | return new St(t2, sp, new Imm(r.index * 4)); 608 | } 609 | ``` 610 | 611 | The function is nothing but a pass on asm function. One thing should be mentioned is that Java IS A STUPID LANGUAGE, so we implement our own link list to make insertion easier. 612 | 613 | ```java 614 | public void insert_before(Inst i, Inst in) { 615 | if (i.prev == null) headInst = in; 616 | else i.prev.next = in; 617 | in.prev = i.prev; in.next = i; i.prev = in; 618 | } 619 | public void insert_after(Inst i, Inst in) { 620 | if (i.next == null) tailInst = in; 621 | else i.next.prev = in; 622 | in.prev = i; in.next = i.next; i.next = in; 623 | } 624 | ``` 625 | 626 | It should be mentioned that the stack length should be carefully maintained. In this stupid algorithm and language, the stack length straightly equals $\# \text{ of virtual registers} \times 4$ Bytes, but with function call(which requires some stack space if parameters are too many) and better register allocation algorithm, the stack length is known after register allocation. In this case, you should consider how to fill in the value of Immediate values(`Imm` class in above) as the offset of `store` and `load` instructions. -------------------------------------------------------------------------------- /Yx.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/AST/ASTNode.java: -------------------------------------------------------------------------------- 1 | package AST; 2 | 3 | import Util.position; 4 | 5 | abstract public class ASTNode { 6 | public position pos; 7 | 8 | public ASTNode(position pos) { 9 | this.pos = pos; 10 | } 11 | 12 | abstract public void accept(ASTVisitor visitor); 13 | } 14 | -------------------------------------------------------------------------------- /src/AST/ASTVisitor.java: -------------------------------------------------------------------------------- 1 | package AST; 2 | 3 | public interface ASTVisitor { 4 | void visit(RootNode it); 5 | void visit(structDefNode it); 6 | void visit(FnRootNode it); 7 | 8 | void visit(varDefStmtNode it); 9 | void visit(returnStmtNode it); 10 | void visit(blockStmtNode it); 11 | void visit(exprStmtNode it); 12 | void visit(ifStmtNode it); 13 | 14 | void visit(assignExprNode it); 15 | void visit(binaryExprNode it); 16 | void visit(constExprNode it); 17 | void visit(cmpExprNode it); 18 | void visit(varExprNode it); 19 | } 20 | -------------------------------------------------------------------------------- /src/AST/ExprNode.java: -------------------------------------------------------------------------------- 1 | package AST; 2 | 3 | import MIR.entity; 4 | import Util.Type; 5 | import Util.position; 6 | 7 | public abstract class ExprNode extends ASTNode { 8 | public Type type; 9 | public entity val; 10 | 11 | public ExprNode(position pos) { 12 | super(pos); 13 | } 14 | 15 | public boolean isAssignable() { 16 | return false; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/AST/FnRootNode.java: -------------------------------------------------------------------------------- 1 | package AST; 2 | import Util.Type; 3 | import Util.position; 4 | 5 | import java.util.ArrayList; 6 | 7 | public class FnRootNode extends ASTNode { 8 | public ArrayList stmts; 9 | public Type intType, boolType; 10 | 11 | public FnRootNode(position pos) { 12 | super(pos); 13 | stmts = new ArrayList<>(); 14 | intType = new Type(); 15 | boolType = new Type(); 16 | intType.isInt = true; 17 | boolType.isBool = true; 18 | } 19 | 20 | @Override 21 | public void accept(ASTVisitor visitor) { 22 | visitor.visit(this); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/AST/RootNode.java: -------------------------------------------------------------------------------- 1 | package AST; 2 | 3 | import Util.position; 4 | 5 | import java.util.ArrayList; 6 | 7 | public class RootNode extends ASTNode { 8 | public FnRootNode fn; 9 | public ArrayList strDefs = new ArrayList<>(); 10 | 11 | public RootNode(position pos, FnRootNode fn) { 12 | super(pos); 13 | this.fn = fn; 14 | } 15 | 16 | @Override 17 | public void accept(ASTVisitor visitor) { 18 | visitor.visit(this); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/AST/StmtNode.java: -------------------------------------------------------------------------------- 1 | package AST; 2 | 3 | import Util.position; 4 | 5 | public abstract class StmtNode extends ASTNode { 6 | public StmtNode(position pos) { 7 | super(pos); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/AST/assignExprNode.java: -------------------------------------------------------------------------------- 1 | package AST; 2 | 3 | import Util.Type; 4 | import Util.position; 5 | 6 | public class assignExprNode extends ExprNode{ 7 | public ExprNode lhs, rhs; 8 | 9 | public assignExprNode(ExprNode lhs, ExprNode rhs, position pos) { 10 | super(pos); 11 | this.lhs = lhs; 12 | this.rhs = rhs; 13 | } 14 | 15 | @Override 16 | public void accept(ASTVisitor visitor) { 17 | visitor.visit(this); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/AST/binaryExprNode.java: -------------------------------------------------------------------------------- 1 | package AST; 2 | 3 | import Util.Type; 4 | import Util.position; 5 | 6 | public class binaryExprNode extends ExprNode { 7 | public ExprNode lhs, rhs; 8 | public enum binaryOpType { 9 | add, sub 10 | } 11 | public binaryOpType opCode; 12 | 13 | public binaryExprNode(ExprNode lhs, ExprNode rhs, binaryOpType opCode, Type intType, position pos) { 14 | super(pos); 15 | this.lhs = lhs; 16 | this.rhs = rhs; 17 | this.opCode = opCode; 18 | type = intType; 19 | } 20 | 21 | @Override 22 | public void accept(ASTVisitor visitor) { 23 | visitor.visit(this); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/AST/blockStmtNode.java: -------------------------------------------------------------------------------- 1 | package AST; 2 | 3 | import Util.position; 4 | 5 | import java.util.ArrayList; 6 | 7 | public class blockStmtNode extends StmtNode { 8 | public ArrayList stmts; 9 | 10 | public blockStmtNode(position pos) { 11 | super(pos); 12 | this.stmts = new ArrayList<>(); 13 | } 14 | 15 | @Override 16 | public void accept(ASTVisitor visitor) { 17 | visitor.visit(this); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/AST/cmpExprNode.java: -------------------------------------------------------------------------------- 1 | package AST; 2 | 3 | import Util.Type; 4 | import Util.position; 5 | 6 | public class cmpExprNode extends ExprNode { 7 | public ExprNode lhs, rhs; 8 | public enum cmpOpType { 9 | eq, neq 10 | } 11 | public cmpOpType opCode; 12 | 13 | public cmpExprNode(ExprNode lhs, ExprNode rhs, cmpOpType opCode, Type boolType, position pos) { 14 | super(pos); 15 | this.lhs = lhs; 16 | this.rhs = rhs; 17 | this.opCode = opCode; 18 | type = boolType; 19 | } 20 | 21 | @Override 22 | public void accept(ASTVisitor visitor) { 23 | visitor.visit(this); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/AST/constExprNode.java: -------------------------------------------------------------------------------- 1 | package AST; 2 | 3 | import Util.position; 4 | 5 | import Util.Type; 6 | 7 | public class constExprNode extends ExprNode { 8 | public int value; 9 | 10 | public constExprNode(int value, Type intType, position pos) { 11 | super(pos); 12 | this.value = value; 13 | type = intType; 14 | } 15 | 16 | @Override 17 | public void accept(ASTVisitor visitor) { 18 | visitor.visit(this); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/AST/exprStmtNode.java: -------------------------------------------------------------------------------- 1 | package AST; 2 | 3 | import Util.position; 4 | 5 | public class exprStmtNode extends StmtNode{ 6 | public ExprNode expr; 7 | 8 | public exprStmtNode(ExprNode expr, position pos) { 9 | super(pos); 10 | this.expr = expr; 11 | } 12 | 13 | @Override 14 | public void accept(ASTVisitor visitor) { 15 | visitor.visit(this); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/AST/ifStmtNode.java: -------------------------------------------------------------------------------- 1 | package AST; 2 | 3 | import Util.position; 4 | 5 | public class ifStmtNode extends StmtNode { 6 | public ExprNode condition; 7 | public StmtNode thenStmt, elseStmt; 8 | 9 | public ifStmtNode(ExprNode condition, StmtNode thenStmt, StmtNode elseStmt, position pos) { 10 | super(pos); 11 | this.condition = condition; 12 | this.thenStmt = thenStmt; 13 | this.elseStmt = elseStmt; 14 | } 15 | 16 | @Override 17 | public void accept(ASTVisitor visitor) { 18 | visitor.visit(this); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/AST/returnStmtNode.java: -------------------------------------------------------------------------------- 1 | package AST; 2 | 3 | import Util.position; 4 | 5 | public class returnStmtNode extends StmtNode { 6 | public ExprNode value; 7 | 8 | public returnStmtNode(ExprNode value, position pos) { 9 | super(pos); 10 | this.value = value; 11 | } 12 | 13 | @Override 14 | public void accept(ASTVisitor visitor) { 15 | visitor.visit(this); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/AST/structDefNode.java: -------------------------------------------------------------------------------- 1 | package AST; 2 | 3 | import Util.position; 4 | 5 | import java.util.ArrayList; 6 | 7 | public class structDefNode extends ASTNode { 8 | public ArrayList varDefs = new ArrayList<>(); 9 | public String name; 10 | 11 | public structDefNode(position pos, String name) { 12 | super(pos); 13 | this.name = name; 14 | } 15 | 16 | @Override 17 | public void accept(ASTVisitor visitor) { 18 | visitor.visit(this); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/AST/varDefStmtNode.java: -------------------------------------------------------------------------------- 1 | package AST; 2 | 3 | import Util.position; 4 | 5 | public class varDefStmtNode extends StmtNode { 6 | public String name, typeName; 7 | public ExprNode init; 8 | 9 | public varDefStmtNode(String typeName, String name, ExprNode init, position pos) { 10 | super(pos); 11 | this.name = name; 12 | this.typeName = typeName; 13 | this.init = init; 14 | } 15 | 16 | @Override 17 | public void accept(ASTVisitor visitor) { 18 | visitor.visit(this); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/AST/varExprNode.java: -------------------------------------------------------------------------------- 1 | package AST; 2 | 3 | import Util.Type; 4 | import Util.position; 5 | 6 | public class varExprNode extends ExprNode { 7 | public String name; 8 | 9 | public varExprNode(String name, position pos) { 10 | super(pos); 11 | this.name = name; 12 | type = null; 13 | } 14 | 15 | @Override 16 | public void accept(ASTVisitor visitor) { 17 | visitor.visit(this); 18 | } 19 | 20 | @Override 21 | public boolean isAssignable() {return true;} 22 | } 23 | -------------------------------------------------------------------------------- /src/Assembly/AsmBlock.java: -------------------------------------------------------------------------------- 1 | package Assembly; 2 | 3 | import Assembly.Inst.Inst; 4 | 5 | import java.util.HashSet; 6 | 7 | public class AsmBlock { 8 | public Inst headInst = null, tailInst = null; 9 | public HashSet successors = new HashSet<>(); 10 | public int index = -1; 11 | // prune-use: public AsmBlock precursor = null; 12 | 13 | public AsmBlock() {} 14 | 15 | 16 | public void push_back(Inst i) { 17 | if (headInst == null) headInst = tailInst = i; 18 | else { 19 | tailInst.next = i; 20 | i.prev = tailInst; 21 | tailInst = i; 22 | } 23 | } 24 | public void insert_before(Inst i, Inst in) { 25 | if (i.prev == null) headInst = in; 26 | else i.prev.next = in; 27 | in.prev = i.prev; in.next = i; i.prev = in; 28 | } 29 | public void insert_after(Inst i, Inst in) { 30 | if (i.next == null) tailInst = in; 31 | else i.next.prev = in; 32 | in.prev = i; in.next = i.next; i.next = in; 33 | } 34 | 35 | @Override 36 | public String toString() { 37 | return "." + index; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Assembly/AsmFn.java: -------------------------------------------------------------------------------- 1 | package Assembly; 2 | 3 | import Assembly.Operand.PhyReg; 4 | 5 | import java.util.ArrayList; 6 | import java.util.Arrays; 7 | import java.util.HashSet; 8 | import java.util.Set; 9 | 10 | public class AsmFn { 11 | public static ArrayList phyRegName = new ArrayList<>(Arrays.asList( 12 | "zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", 13 | "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", 14 | "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6")); 15 | 16 | public Set blocks = new HashSet<>(); 17 | public AsmBlock rootBlock = null; 18 | public ArrayList phyRegs; 19 | public int stackLength = 0; 20 | 21 | public AsmFn() { 22 | phyRegs = new ArrayList<>(); 23 | for (int i = 0; i < 32;++i) { 24 | phyRegs.add(new PhyReg(phyRegName.get(i))); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Assembly/Inst/Bz.java: -------------------------------------------------------------------------------- 1 | package Assembly.Inst; 2 | 3 | import Assembly.AsmBlock; 4 | import Assembly.Operand.Reg; 5 | import Assembly.Operand.VirtualReg; 6 | 7 | // This is actually Beqz, that is jump if src == 0: jump to falseBranch 8 | public class Bz extends Inst { 9 | public Reg src; 10 | public AsmBlock destination; 11 | 12 | public Bz(Reg src, AsmBlock destination) { 13 | this.src = src; 14 | this.destination = destination; 15 | } 16 | 17 | @Override 18 | public String toString() { 19 | return "beqz " + src.toString() + ", " + destination.toString(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Assembly/Inst/IType.java: -------------------------------------------------------------------------------- 1 | package Assembly.Inst; 2 | 3 | import Assembly.Operand.Imm; 4 | import Assembly.Operand.Reg; 5 | 6 | public class IType extends Inst { 7 | public Reg rd, rs; 8 | public Imm imm; 9 | public CalCategory op; 10 | 11 | public IType(Reg rd, Reg rs, Imm imm, CalCategory op) { 12 | this.rd = rd; 13 | this.rs = rs; 14 | this.imm = imm; 15 | this.op = op; 16 | } 17 | 18 | @Override 19 | public String toString() { 20 | if (op.ordinal() < 2) return op + "i " + rd + ", " + rs + ", " + imm; 21 | else { 22 | assert(imm.value == 0); 23 | return "s" + op + "z " + rd + ", " + rs; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Assembly/Inst/Inst.java: -------------------------------------------------------------------------------- 1 | package Assembly.Inst; 2 | 3 | public abstract class Inst { 4 | public Inst prev = null, next = null; 5 | public enum CalCategory { 6 | add, sub, eq, ne 7 | } 8 | 9 | // below: for Asm Printer 10 | @Override abstract public String toString(); 11 | } 12 | -------------------------------------------------------------------------------- /src/Assembly/Inst/Jp.java: -------------------------------------------------------------------------------- 1 | package Assembly.Inst; 2 | 3 | import Assembly.AsmBlock; 4 | 5 | public class Jp extends Inst { 6 | public AsmBlock destination; 7 | public Jp(AsmBlock d) { 8 | destination = d; 9 | } 10 | 11 | @Override 12 | public String toString() { 13 | return "j " + destination; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Assembly/Inst/Ld.java: -------------------------------------------------------------------------------- 1 | package Assembly.Inst; 2 | 3 | import Assembly.Operand.Imm; 4 | import Assembly.Operand.PhyReg; 5 | 6 | public class Ld extends Inst{ 7 | public PhyReg rd, addr; 8 | public Imm offset; 9 | 10 | public Ld(PhyReg rd, PhyReg addr, Imm offset) { 11 | this.rd = rd; 12 | this.addr = addr; 13 | this.offset = offset; 14 | } 15 | @Override 16 | public String toString() { 17 | return "lw " + rd + ", " + addr + "(" + offset + ")"; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Assembly/Inst/Li.java: -------------------------------------------------------------------------------- 1 | package Assembly.Inst; 2 | 3 | import Assembly.Operand.Imm; 4 | import Assembly.Operand.Reg; 5 | 6 | public class Li extends Inst { 7 | public Reg rd; 8 | public Imm imm; 9 | 10 | public Li(Reg rd, Imm imm) { 11 | this.rd = rd; 12 | this.imm = imm; 13 | } 14 | 15 | @Override 16 | public String toString() { 17 | return "li " + rd + ", " + imm; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Assembly/Inst/Mv.java: -------------------------------------------------------------------------------- 1 | package Assembly.Inst; 2 | 3 | import Assembly.Operand.Reg; 4 | 5 | public class Mv extends Inst { 6 | public Reg rd, rs1; 7 | 8 | public Mv(Reg rd, Reg rs1) { 9 | this.rd = rd; 10 | this.rs1 = rs1; 11 | } 12 | 13 | @Override 14 | public String toString() { 15 | return "mv " + rd + ", " + rs1; 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /src/Assembly/Inst/RType.java: -------------------------------------------------------------------------------- 1 | package Assembly.Inst; 2 | 3 | import Assembly.Operand.Reg; 4 | import Util.error.internalError; 5 | import Util.position; 6 | 7 | public class RType extends Inst { 8 | public Reg rd, rs1, rs2; 9 | public CalCategory op; 10 | 11 | public RType(Reg rd, Reg rs1, Reg rs2, CalCategory op) { 12 | this.rd = rd; 13 | this.rs1 = rs1; 14 | this.rs2 = rs2; 15 | this.op = op; 16 | } 17 | 18 | @Override 19 | public String toString() { 20 | if (op.ordinal() < 2) return op + " " + rd + ", " + rs1 + ", " + rs2; 21 | else throw new internalError("not correct op for RType", new position(0, 0)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Assembly/Inst/Ret.java: -------------------------------------------------------------------------------- 1 | package Assembly.Inst; 2 | 3 | public class Ret extends Inst { 4 | 5 | @Override 6 | public String toString() { 7 | return "ret"; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Assembly/Inst/St.java: -------------------------------------------------------------------------------- 1 | package Assembly.Inst; 2 | 3 | import Assembly.Operand.Imm; 4 | import Assembly.Operand.PhyReg; 5 | 6 | public class St extends Inst { 7 | public PhyReg rs, addr; 8 | public Imm offset; 9 | 10 | public St(PhyReg rs, PhyReg addr, Imm offset) { 11 | this.rs = rs; 12 | this.addr = addr; 13 | this.offset = offset; 14 | } 15 | @Override 16 | public String toString() { 17 | return "sw " + rs + ", " + addr + "(" + offset + ")"; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Assembly/Operand/Imm.java: -------------------------------------------------------------------------------- 1 | package Assembly.Operand; 2 | 3 | public class Imm extends Operand { 4 | 5 | public int value; 6 | public Imm(int value) { 7 | super(); 8 | this.value = value; 9 | } 10 | 11 | @Override 12 | public String toString() { 13 | return "" + value; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Assembly/Operand/Operand.java: -------------------------------------------------------------------------------- 1 | package Assembly.Operand; 2 | 3 | public abstract class Operand { 4 | } 5 | -------------------------------------------------------------------------------- /src/Assembly/Operand/PhyReg.java: -------------------------------------------------------------------------------- 1 | package Assembly.Operand; 2 | 3 | public class PhyReg extends Reg { 4 | public String name; 5 | public PhyReg(String name) { 6 | this.name = name; 7 | } 8 | 9 | @Override 10 | public String toString() { 11 | return name; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Assembly/Operand/Reg.java: -------------------------------------------------------------------------------- 1 | package Assembly.Operand; 2 | 3 | public abstract class Reg extends Operand { 4 | } 5 | -------------------------------------------------------------------------------- /src/Assembly/Operand/VirtualReg.java: -------------------------------------------------------------------------------- 1 | package Assembly.Operand; 2 | 3 | public class VirtualReg extends Reg { 4 | public int index; 5 | public VirtualReg(int index) { 6 | this.index = index; 7 | } 8 | 9 | @Override 10 | public String toString() { 11 | return "%" + index; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Backend/AsmPrinter.java: -------------------------------------------------------------------------------- 1 | package Backend; 2 | 3 | import Assembly.AsmBlock; 4 | import Assembly.AsmFn; 5 | import Assembly.Inst.Inst; 6 | 7 | import java.io.PrintStream; 8 | import java.util.LinkedList; 9 | import java.util.List; 10 | import java.util.Queue; 11 | 12 | public class AsmPrinter { 13 | private PrintStream out; 14 | 15 | private AsmFn fn; 16 | private int blockCnt = 0; 17 | private List printList = new LinkedList<>(); 18 | 19 | public AsmPrinter(AsmFn fn, PrintStream out) { 20 | this.fn = fn; 21 | this.out = out; 22 | } 23 | 24 | private void rename() { 25 | fn.blocks.forEach(b -> b.index = -1); 26 | Queue queue = new LinkedList<>(); 27 | queue.offer(fn.rootBlock); 28 | fn.rootBlock.index = blockCnt++; 29 | while(!queue.isEmpty()) { 30 | AsmBlock b = queue.poll(); 31 | b.successors.forEach(s -> { 32 | if (s.index == -1){ 33 | s.index = blockCnt++; 34 | queue.offer(s); 35 | } 36 | }); 37 | printList.add(b); 38 | } 39 | } 40 | public void printBlock(AsmBlock b) { 41 | out.println(b + ": "); 42 | for (Inst i = b.headInst; i != null; i = i.next) { 43 | out.println("\t" + i.toString()); 44 | } 45 | } 46 | public void print() { 47 | rename(); 48 | printList.forEach(this::printBlock); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Backend/IRBuilder.java: -------------------------------------------------------------------------------- 1 | package Backend; 2 | 3 | import AST.*; 4 | import MIR.*; 5 | import Util.Scope; 6 | import Util.globalScope; 7 | 8 | import static MIR.binary.opType.add; 9 | import static MIR.binary.opType.sub; 10 | import static MIR.binary.opType.eq; 11 | import static MIR.binary.opType.ne; 12 | 13 | public class IRBuilder implements ASTVisitor { 14 | private block currentBlock; 15 | private mainFn fn; 16 | private Scope currentScope; 17 | private globalScope gScope; 18 | public IRBuilder(mainFn fn, globalScope gScope) { 19 | this.fn = fn; 20 | currentBlock = fn.rootBlock; 21 | currentScope = gScope; 22 | this.gScope = gScope; 23 | } 24 | 25 | @Override 26 | public void visit(RootNode it) { 27 | it.fn.accept(this); 28 | } 29 | 30 | @Override public void visit(structDefNode it) { 31 | 32 | } 33 | 34 | @Override 35 | public void visit(FnRootNode it) { 36 | currentScope = new Scope(currentScope); 37 | it.stmts.forEach(s -> s.accept(this)); 38 | currentScope = currentScope.parentScope(); 39 | } 40 | 41 | @Override 42 | public void visit(varDefStmtNode it) { 43 | currentScope.entities.put(it.name, new register()); 44 | } 45 | 46 | @Override 47 | public void visit(returnStmtNode it) { 48 | entity value; 49 | if (it.value != null) { 50 | it.value.accept(this); 51 | value = it.value.val; 52 | } else value = null; 53 | currentBlock.push_back(new ret(value)); 54 | } 55 | 56 | @Override 57 | public void visit(blockStmtNode it) { 58 | currentScope = new Scope(currentScope); 59 | } 60 | 61 | @Override 62 | public void visit(exprStmtNode it) { 63 | it.expr.accept(this); 64 | } 65 | 66 | @Override 67 | public void visit(ifStmtNode it) { 68 | it.condition.accept(this); 69 | block trueBranch = new block(), falseBranch = new block(); 70 | currentBlock.push_back(new branch(it.condition.val, trueBranch, falseBranch)); 71 | 72 | block destination = new block(); 73 | currentBlock = trueBranch; 74 | it.thenStmt.accept(this); 75 | currentBlock.push_back(new jump(destination)); 76 | currentBlock = falseBranch; 77 | it.elseStmt.accept(this); 78 | currentBlock.push_back(new jump(destination)); 79 | currentBlock = destination; 80 | 81 | fn.blocks.add(trueBranch);fn.blocks.add(falseBranch);fn.blocks.add(destination); 82 | } 83 | 84 | @Override 85 | public void visit(assignExprNode it) { 86 | it.lhs.accept(this); 87 | if (it.rhs instanceof binaryExprNode || 88 | it.rhs instanceof cmpExprNode) { 89 | it.rhs.val = it.lhs.val; 90 | it.rhs.accept(this); 91 | } else { 92 | it.rhs.accept(this); 93 | currentBlock.push_back( 94 | new binary((register) it.lhs.val, it.rhs.val, new constant(0), add) 95 | ); 96 | } 97 | } 98 | 99 | @Override 100 | public void visit(binaryExprNode it) { 101 | it.lhs.accept(this); 102 | it.rhs.accept(this); 103 | register value; 104 | if (it.val != null) value = (register)it.val; 105 | else { 106 | value = new register(); 107 | it.val = value; 108 | } 109 | binary.opType op = it.opCode == binaryExprNode.binaryOpType.add ? add : sub; 110 | currentBlock.push_back(new binary(value, it.lhs.val, it.rhs.val, op)); 111 | } 112 | 113 | @Override 114 | public void visit(constExprNode it) { 115 | it.val = new constant(it.value); 116 | } 117 | 118 | @Override 119 | public void visit(cmpExprNode it) { 120 | it.lhs.accept(this); 121 | it.rhs.accept(this); 122 | register value; 123 | if (it.val != null) value = (register)it.val; 124 | else { 125 | value = new register(); 126 | it.val = value; 127 | } 128 | binary.opType op = it.opCode == cmpExprNode.cmpOpType.eq ? eq : ne; 129 | currentBlock.push_back(new binary(value, it.lhs.val, it.rhs.val, op)); 130 | } 131 | 132 | @Override 133 | public void visit(varExprNode it) { 134 | it.val = currentScope.getEntity(it.name, true); 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/Backend/IRPrinter.java: -------------------------------------------------------------------------------- 1 | package Backend; 2 | 3 | import MIR.*; 4 | 5 | import java.io.PrintStream; 6 | import java.util.HashMap; 7 | 8 | public class IRPrinter implements Pass { 9 | private PrintStream out; 10 | 11 | private int blockCnt = 0, regCnt = 0; 12 | private HashMap blockIndex = new HashMap<>(); 13 | private HashMap regIndex = new HashMap<>(); 14 | 15 | public IRPrinter(PrintStream out) { 16 | this.out = out; 17 | } 18 | 19 | public void visitBlock(block b) { 20 | out.println(getBlockName(b) + ": "); 21 | b.stmts().forEach(this::print); 22 | b.successors().forEach(this::visitBlock); 23 | } 24 | 25 | @Override 26 | public void visitFn(mainFn f) { 27 | visitBlock(f.rootBlock); 28 | } 29 | 30 | private String getBlockName(block b) { 31 | if (blockIndex.containsKey(b)) return "b." + blockIndex.get(b); 32 | else { 33 | blockIndex.put(b, blockCnt++); 34 | return "b." + (blockCnt - 1); 35 | } 36 | } 37 | private String getRegName(register r) { 38 | if (regIndex.containsKey(r)) return "%" + regIndex.get(r); 39 | else { 40 | regIndex.put(r, regCnt++); 41 | return "%" + (regCnt - 1); 42 | } 43 | } 44 | private String getEntityString(entity e) { 45 | if (e instanceof register) return getRegName((register) e); 46 | else return ((constant) e).value() + ""; 47 | } 48 | private String getOpString(binary.opType op) { 49 | if (op == binary.opType.add) return "+"; 50 | else if (op == binary.opType.sub) return "-"; 51 | else if (op == binary.opType.eq) return "=="; 52 | else return "!="; 53 | } 54 | 55 | private void print(statement s) { 56 | if (s instanceof binary) { 57 | binary b = (binary) s; 58 | out.println("\t" + getRegName(b.lhs) + " = " + 59 | getEntityString(b.op1) + " " + getOpString(b.op) + 60 | " " + getEntityString(b.op2) + ";"); 61 | } else if (s instanceof jump) { 62 | jump j = (jump) s; 63 | out.println("\tj " + getBlockName(j.destination) + ";"); 64 | } else if (s instanceof branch) { 65 | branch b = (branch) s; 66 | out.println("\tbr " + getEntityString(b.op) + " " + 67 | getBlockName(b.trueBranch) + ", " + getBlockName(b.falseBranch) + ";"); 68 | } else if (s instanceof ret) { 69 | ret r = (ret) s; 70 | out.println("\tret" + (r.value == null ? "" : 71 | (" " + getEntityString(r.value))) + ";"); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/Backend/InstSelector.java: -------------------------------------------------------------------------------- 1 | package Backend; 2 | 3 | import Assembly.*; 4 | import Assembly.Inst.*; 5 | import Assembly.Operand.*; 6 | import MIR.*; 7 | 8 | import java.util.HashMap; 9 | import static Assembly.Inst.Inst.CalCategory.*; 10 | 11 | public class InstSelector implements Pass { 12 | private HashMap blockMap = new HashMap<>(); 13 | private HashMap regMap = new HashMap<>(); 14 | private int cnt = 0; 15 | 16 | public AsmFn mainF; 17 | public InstSelector(AsmFn mainFn) { 18 | this.mainF = mainFn; 19 | } 20 | 21 | private AsmBlock getAsmBlock(block b) { 22 | if (!blockMap.containsKey(b)) { 23 | blockMap.put(b, new AsmBlock()); 24 | } 25 | return blockMap.get(b); 26 | } 27 | private VirtualReg getAsmReg(register r) { 28 | if (!regMap.containsKey(r)) { 29 | regMap.put(r, new VirtualReg(cnt++)); 30 | } 31 | return regMap.get(r); 32 | } 33 | private Imm getImm(constant c) { 34 | return new Imm(c.value()); 35 | } 36 | @Override 37 | public void visitBlock(block B) { 38 | AsmBlock b = getAsmBlock(B); 39 | B.stmts().forEach(s -> { 40 | if (s instanceof jump) { 41 | jump j = (jump) s; 42 | b.push_back(new Jp(getAsmBlock(j.destination))); 43 | b.successors.add(getAsmBlock(j.destination)); 44 | } else if (s instanceof branch) { 45 | branch br = (branch) s; 46 | VirtualReg src; 47 | if (br.op instanceof constant) { 48 | src = new VirtualReg(cnt++); 49 | b.push_back(new Li(src, getImm((constant) br.op))); 50 | } 51 | else src = getAsmReg((register) br.op); 52 | b.push_back(new Bz(src, getAsmBlock(br.falseBranch))); 53 | b.successors.add(getAsmBlock(br.falseBranch)); 54 | AsmBlock suc = getAsmBlock(br.trueBranch); 55 | // if (suc.precursor == null) suc.precursor = b; 56 | // else // prune-use 57 | b.push_back(new Jp(suc)); 58 | b.successors.add(suc); 59 | } else if (s instanceof ret) { 60 | ret r = (ret) s; 61 | if (r.value != null) { 62 | if (r.value instanceof register) 63 | b.push_back( 64 | new Mv(mainF.phyRegs.get(10), getAsmReg((register) r.value)) 65 | ); 66 | else b.push_back( 67 | new Li(mainF.phyRegs.get(10), getImm((constant) r.value)) 68 | ); 69 | } // First move the return value to x10, then return 70 | b.push_back(new Ret()); 71 | } else if (s instanceof binary) { 72 | binary bi = (binary) s; 73 | Inst.CalCategory op = bi.op == binary.opType.add ? add : sub; 74 | Reg rd; 75 | if (bi.op == binary.opType.eq || bi.op == binary.opType.ne) 76 | rd = new VirtualReg(cnt++); 77 | else rd = getAsmReg(bi.lhs); 78 | if (bi.op1 instanceof constant) { 79 | b.push_back(new Li(rd, getImm((constant) bi.op2))); 80 | } else if (bi.op2 instanceof constant) { 81 | b.push_back(new IType(rd, 82 | getAsmReg((register)bi.op1), 83 | getImm((constant) bi.op2), 84 | op) 85 | ); 86 | } else { 87 | b.push_back(new RType(rd, 88 | getAsmReg((register) bi.op1), 89 | getAsmReg((register) bi.op2), 90 | op)); 91 | } 92 | if (bi.op == binary.opType.eq) 93 | b.push_back(new IType(getAsmReg(bi.lhs), rd, new Imm(0), eq)); 94 | else if (bi.op == binary.opType.ne) 95 | b.push_back(new IType(getAsmReg(bi.lhs), rd, new Imm(0), ne)); 96 | // Assembly code only has seqz and snez, no seq and sne 97 | } 98 | }); 99 | } 100 | 101 | @Override 102 | public void visitFn(mainFn f) { 103 | f.blocks.forEach(B -> mainF.blocks.add(getAsmBlock(B))); 104 | mainF.rootBlock = getAsmBlock(f.rootBlock); 105 | f.blocks.forEach(this::visitBlock); 106 | mainF.stackLength += 4 * cnt; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/Backend/Pass.java: -------------------------------------------------------------------------------- 1 | package Backend; 2 | 3 | import MIR.block; 4 | import MIR.mainFn; 5 | 6 | public interface Pass { 7 | void visitBlock(block b); 8 | void visitFn(mainFn f); 9 | } 10 | -------------------------------------------------------------------------------- /src/Backend/RegAlloc.java: -------------------------------------------------------------------------------- 1 | package Backend; 2 | 3 | import Assembly.AsmFn; 4 | import Assembly.Inst.*; 5 | import Assembly.Operand.*; 6 | 7 | public class RegAlloc { 8 | public AsmFn f; 9 | private PhyReg sp, t0, t1, t2; 10 | public RegAlloc(AsmFn f) { 11 | this.f = f; 12 | sp = f.phyRegs.get(2); 13 | t0 = f.phyRegs.get(5); 14 | t1 = f.phyRegs.get(6); 15 | t2 = f.phyRegs.get(7); 16 | } 17 | 18 | private Inst loadVirtualReg(VirtualReg r, PhyReg rd) { 19 | return new Ld(rd, sp, new Imm(r.index * 4)); 20 | } 21 | private Inst storeVirtualReg(VirtualReg r) { 22 | return new St(t2, sp, new Imm(r.index * 4)); 23 | } 24 | public void work() { 25 | f.blocks.forEach(b -> { 26 | for (Inst i = b.headInst; i != null; i = i.next) { 27 | if (i instanceof Bz) { 28 | Bz bz = (Bz) i; 29 | b.insert_before(i, loadVirtualReg((VirtualReg) bz.src, t0)); 30 | bz.src = t0; 31 | } else if (i instanceof IType) { 32 | IType it = (IType) i; 33 | b.insert_before(i, loadVirtualReg((VirtualReg) it.rs, t0)); 34 | it.rs = t0; 35 | b.insert_after(i, storeVirtualReg((VirtualReg) it.rd)); 36 | it.rd = t2; 37 | } else if (i instanceof Li) { 38 | Li l = (Li) i; 39 | if (l.rd instanceof VirtualReg) //return 0; 40 | b.insert_after(i, storeVirtualReg((VirtualReg) l.rd)); 41 | l.rd = t2; 42 | } else if (i instanceof Mv) { 43 | Mv m = (Mv) i; 44 | b.insert_before(i, loadVirtualReg((VirtualReg)m.rs1, t0)); 45 | m.rs1 = t0; 46 | if (m.rd instanceof VirtualReg) //return x; 47 | b.insert_after(i, storeVirtualReg((VirtualReg)m.rd)); 48 | m.rd = t2; 49 | } else if (i instanceof RType) { 50 | RType r = (RType) i; 51 | b.insert_before(i, loadVirtualReg((VirtualReg) r.rs1, t0)); 52 | r.rs1 = t0; 53 | b.insert_before(i, loadVirtualReg((VirtualReg) r.rs2, t1)); 54 | r.rs2 = t1; 55 | b.insert_after(i, storeVirtualReg((VirtualReg) r.rd)); 56 | r.rd = t2; 57 | } 58 | } 59 | }); 60 | f.rootBlock.insert_before(f.rootBlock.headInst, 61 | new IType(sp, sp, new Imm(f.stackLength * -1), Inst.CalCategory.add) 62 | ); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/Frontend/ASTBuilder.java: -------------------------------------------------------------------------------- 1 | package Frontend; 2 | 3 | import AST.*; 4 | import Parser.YxBaseVisitor; 5 | import Parser.YxParser; 6 | import Util.Type; 7 | import Util.globalScope; 8 | import Util.position; 9 | import org.antlr.v4.runtime.ParserRuleContext; 10 | import AST.binaryExprNode.binaryOpType; 11 | import AST.cmpExprNode.cmpOpType; 12 | 13 | public class ASTBuilder extends YxBaseVisitor { 14 | 15 | private globalScope gScope; 16 | public ASTBuilder(globalScope gScope) { 17 | this.gScope = gScope; 18 | } 19 | 20 | Type intType, boolType; 21 | 22 | @Override public ASTNode visitProgram(YxParser.ProgramContext ctx) { 23 | RootNode root = new RootNode(new position(ctx), (FnRootNode)visit(ctx.mainFn())); 24 | ctx.classDef().forEach(cd -> root.strDefs.add((structDefNode) visit(cd))); 25 | return root; 26 | } 27 | 28 | @Override public ASTNode visitClassDef(YxParser.ClassDefContext ctx) { 29 | structDefNode structDef = new structDefNode(new position(ctx), ctx.Identifier().toString()); 30 | ctx.varDef().forEach(vd -> structDef.varDefs.add((varDefStmtNode) visit(vd))); 31 | return structDef; 32 | } 33 | 34 | @Override public ASTNode visitMainFn(YxParser.MainFnContext ctx) { 35 | FnRootNode root = new FnRootNode(new position(ctx)); 36 | intType = root.intType; 37 | boolType = root.boolType; 38 | gScope.addType("int", intType, root.pos); 39 | gScope.addType("bool", boolType, root.pos); 40 | 41 | if (ctx.suite() != null) { 42 | for (ParserRuleContext stmt : ctx.suite().statement()) 43 | root.stmts.add((StmtNode) visit(stmt)); 44 | } 45 | return root; 46 | } 47 | 48 | @Override public ASTNode visitVarDef(YxParser.VarDefContext ctx) { 49 | ExprNode expr = null; 50 | String typeName; 51 | if (ctx.type().Int() != null) typeName = ctx.type().Int().toString(); 52 | else typeName = ctx.type().Identifier().toString(); 53 | if (ctx.expression() != null) expr = (ExprNode)visit(ctx.expression()); 54 | 55 | return new varDefStmtNode(typeName, 56 | ctx.Identifier().toString(), 57 | expr, new position(ctx)); 58 | } 59 | 60 | @Override public ASTNode visitSuite(YxParser.SuiteContext ctx) { 61 | blockStmtNode node = new blockStmtNode(new position(ctx)); 62 | 63 | if (!ctx.statement().isEmpty()) { 64 | for (ParserRuleContext stmt : ctx.statement()) { 65 | StmtNode tmp = (StmtNode)visit(stmt); 66 | if (tmp != null) node.stmts.add(tmp); 67 | } 68 | } 69 | return node; 70 | } 71 | 72 | @Override public ASTNode visitBlock(YxParser.BlockContext ctx) { 73 | return visit(ctx.suite()); 74 | } 75 | 76 | @Override public ASTNode visitVardefStmt(YxParser.VardefStmtContext ctx) { return visit(ctx.varDef()); } 77 | 78 | @Override public ASTNode visitIfStmt(YxParser.IfStmtContext ctx) { 79 | StmtNode thenStmt = (StmtNode)visit(ctx.trueStmt), elseStmt = null; 80 | ExprNode condition = (ExprNode)visit(ctx.expression()); 81 | if (ctx.falseStmt != null) elseStmt = (StmtNode)visit(ctx.falseStmt); 82 | return new ifStmtNode(condition, thenStmt, elseStmt, new position(ctx)); 83 | } 84 | 85 | @Override public ASTNode visitReturnStmt(YxParser.ReturnStmtContext ctx) { 86 | ExprNode value = null; 87 | if (ctx.expression() != null) value = (ExprNode) visit(ctx.expression()); 88 | return new returnStmtNode(value, new position(ctx)); 89 | } 90 | 91 | @Override public ASTNode visitPureExprStmt(YxParser.PureExprStmtContext ctx) { 92 | return new exprStmtNode((ExprNode) visit(ctx.expression()), new position(ctx)); 93 | } 94 | 95 | @Override public ASTNode visitEmptyStmt(YxParser.EmptyStmtContext ctx) { 96 | return null; 97 | } 98 | 99 | @Override public ASTNode visitAtomExpr(YxParser.AtomExprContext ctx) { 100 | return visit(ctx.primary()); 101 | } 102 | 103 | @Override public ASTNode visitBinaryExpr(YxParser.BinaryExprContext ctx) { 104 | ExprNode lhs = (ExprNode) visit(ctx.expression(0)), 105 | rhs = (ExprNode) visit(ctx.expression(1)); 106 | binaryOpType biOp = ctx.Plus() != null ? binaryOpType.add : 107 | (ctx.Minus() != null ? binaryOpType.sub : null); 108 | cmpOpType cmpOp = ctx.Equal() != null ? cmpOpType.eq : 109 | (ctx.NotEqual() != null ? cmpOpType.neq : null); 110 | 111 | return biOp != null ? (new binaryExprNode(lhs, rhs, biOp, intType, new position(ctx))) : 112 | (new cmpExprNode(lhs, rhs, cmpOp, boolType, new position(ctx))); 113 | } 114 | 115 | @Override public ASTNode visitAssignExpr(YxParser.AssignExprContext ctx) { 116 | ExprNode lhs = (ExprNode) visit(ctx.expression(0)), 117 | rhs = (ExprNode) visit(ctx.expression(1)); 118 | return new assignExprNode(lhs, rhs, new position(ctx)); 119 | } 120 | 121 | @Override public ASTNode visitPrimary(YxParser.PrimaryContext ctx) { 122 | if (ctx.expression() != null) return visit(ctx.expression()); 123 | else if (ctx.literal() != null) return visit(ctx.literal()); 124 | else return new varExprNode(ctx.Identifier().toString(), new position(ctx.Identifier())); 125 | } 126 | 127 | @Override public ASTNode visitLiteral(YxParser.LiteralContext ctx) { 128 | return new constExprNode(Integer.parseInt(ctx.DecimalInteger().toString()), 129 | intType, new position(ctx)); 130 | } 131 | 132 | } 133 | -------------------------------------------------------------------------------- /src/Frontend/SemanticChecker.java: -------------------------------------------------------------------------------- 1 | package Frontend; 2 | 3 | import AST.*; 4 | import Util.Scope; 5 | import Util.Type; 6 | import Util.error.semanticError; 7 | import Util.globalScope; 8 | 9 | public class SemanticChecker implements ASTVisitor { 10 | private Scope currentScope; 11 | private globalScope gScope; 12 | private Type currentStruct = null; 13 | 14 | public SemanticChecker(globalScope gScope) { 15 | currentScope = this.gScope = gScope; 16 | } 17 | 18 | @Override 19 | public void visit(RootNode it) { 20 | it.strDefs.forEach(sd -> sd.accept(this)); 21 | // we SHOULD check struct definitions first 22 | it.fn.accept(this); 23 | } 24 | 25 | @Override 26 | public void visit(structDefNode it) { 27 | currentStruct = gScope.getTypeFromName(it.name, it.pos); 28 | it.varDefs.forEach(vd -> vd.accept(this)); 29 | currentStruct = null; 30 | } 31 | 32 | @Override 33 | public void visit(FnRootNode it) { 34 | currentScope = new Scope(currentScope); 35 | for (StmtNode stmt : it.stmts) stmt.accept(this); 36 | } 37 | 38 | @Override 39 | public void visit(varDefStmtNode it) { 40 | if (currentStruct != null) { 41 | assert (currentStruct.members != null); 42 | if (currentStruct.members.containsKey(it.name)) 43 | throw new semanticError("redefinition of member " + it.name, it.pos); 44 | currentStruct.members.put(it.name, gScope.getTypeFromName(it.typeName, it.pos)); 45 | if (it.init != null) 46 | throw new semanticError("Yx does not support default init of members", 47 | it.init.pos); 48 | } 49 | 50 | if (it.init != null) { 51 | it.init.accept(this); 52 | if (!it.init.type.isInt) 53 | throw new semanticError("Semantic Error: type not match. It should be int", 54 | it.init.pos); 55 | } 56 | currentScope.defineVariable(it.name, gScope.getTypeFromName(it.typeName, it.pos), it.pos); 57 | } 58 | 59 | @Override 60 | public void visit(returnStmtNode it) { 61 | if (it.value != null) { 62 | it.value.accept(this); 63 | if (!it.value.type.isInt) 64 | throw new semanticError("Semantic Error: type not match. It should be int", 65 | it.value.pos); 66 | } 67 | } 68 | 69 | @Override 70 | public void visit(blockStmtNode it) { 71 | if (!it.stmts.isEmpty()) { 72 | currentScope = new Scope(currentScope); 73 | for (StmtNode stmt : it.stmts) stmt.accept(this); 74 | currentScope = currentScope.parentScope(); 75 | } 76 | } 77 | 78 | @Override 79 | public void visit(exprStmtNode it) { 80 | it.expr.accept(this); 81 | } 82 | 83 | @Override 84 | public void visit(ifStmtNode it) { 85 | it.condition.accept(this); 86 | if (!it.condition.type.isBool) 87 | throw new semanticError("Semantic Error: type not match. It should be bool", 88 | it.condition.pos); 89 | it.thenStmt.accept(this); 90 | if (it.elseStmt != null) it.elseStmt.accept(this); 91 | } 92 | 93 | @Override 94 | public void visit(assignExprNode it) { 95 | it.rhs.accept(this); 96 | it.lhs.accept(this); 97 | if (it.rhs.type != it.lhs.type) 98 | throw new semanticError("Semantic Error: type not match. ", it.pos); 99 | if (!it.lhs.isAssignable()) 100 | throw new semanticError("Semantic Error: not assignable", it.lhs.pos); 101 | it.type = it.rhs.type; 102 | } 103 | 104 | @Override 105 | public void visit(binaryExprNode it) { 106 | it.lhs.accept(this); 107 | it.rhs.accept(this); 108 | if (!it.lhs.type.isInt) 109 | throw new semanticError("Semantic error: type not match. It should be int", 110 | it.lhs.pos); 111 | if (!it.rhs.type.isInt) 112 | throw new semanticError("Semantic error: type not match. It should be int", 113 | it.rhs.pos); 114 | } 115 | 116 | @Override 117 | public void visit(constExprNode it) {} 118 | 119 | @Override 120 | public void visit(cmpExprNode it) { 121 | it.lhs.accept(this); 122 | it.rhs.accept(this); 123 | if (it.rhs.type != it.lhs.type) 124 | throw new semanticError("Semantic Error: type not match. ", it.pos); 125 | } 126 | 127 | @Override 128 | public void visit(varExprNode it) { 129 | if (!currentScope.containsVariable(it.name, true)) 130 | throw new semanticError("Semantic Error: variable not defined. ", it.pos); 131 | it.type = currentScope.getType(it.name, true); 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/Frontend/SymbolCollector.java: -------------------------------------------------------------------------------- 1 | package Frontend; 2 | 3 | import AST.*; 4 | import Util.Type; 5 | import Util.globalScope; 6 | 7 | import java.util.HashMap; 8 | 9 | public class SymbolCollector implements ASTVisitor { 10 | private globalScope gScope; 11 | public SymbolCollector(globalScope gScope) { 12 | this.gScope = gScope; 13 | } 14 | @Override 15 | public void visit(RootNode it) { 16 | it.strDefs.forEach(sd -> sd.accept(this)); 17 | } 18 | 19 | @Override public void visit(structDefNode it) { 20 | Type struct = new Type(); 21 | struct.members = new HashMap<>(); 22 | it.varDefs.forEach(vd -> vd.accept(this)); 23 | gScope.addType(it.name, struct, it.pos); 24 | } 25 | @Override public void visit(FnRootNode it) {} 26 | @Override public void visit(varDefStmtNode it) {} 27 | @Override public void visit(returnStmtNode it) {} 28 | @Override public void visit(blockStmtNode it) {} 29 | @Override public void visit(exprStmtNode it) {} 30 | @Override public void visit(ifStmtNode it) {} 31 | @Override public void visit(assignExprNode it) {} 32 | @Override public void visit(binaryExprNode it) {} 33 | @Override public void visit(constExprNode it) {} 34 | @Override public void visit(cmpExprNode it) {} 35 | @Override public void visit(varExprNode it) {} 36 | } 37 | -------------------------------------------------------------------------------- /src/MIR/binary.java: -------------------------------------------------------------------------------- 1 | package MIR; 2 | 3 | public class binary extends statement { 4 | public enum opType { 5 | add, sub, eq, ne 6 | } 7 | 8 | public register lhs; 9 | public entity op1, op2; 10 | public opType op; 11 | public binary(register lhs, entity op1, entity op2, opType op) { 12 | super(); 13 | this.lhs = lhs; 14 | this.op1 = op1; 15 | this.op2 = op2; 16 | this.op = op; 17 | if (this.op1 instanceof constant) { 18 | this.op1 = op2; 19 | this.op2 = op1; 20 | if (this.op1 instanceof constant) { 21 | int i1 = ((constant) op1).value(), i2 = ((constant) op2).value(), i; 22 | if (op == opType.add) i = i1 + i2; 23 | else if (op == opType.sub) i = i1 - i2; 24 | else if (op == opType.eq) i = (i1 == i2) ? 1 : 0; 25 | else i = (i1 != i2) ? 1 : 0; 26 | this.op2 = new constant(i); 27 | this.op1 = new constant(0); 28 | } 29 | } 30 | // Now, op1 is either register or zero 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/MIR/block.java: -------------------------------------------------------------------------------- 1 | package MIR; 2 | 3 | import Util.error.internalError; 4 | import Util.position; 5 | 6 | import java.util.ArrayList; 7 | import java.util.LinkedList; 8 | 9 | public class block { 10 | private LinkedList stmts = new LinkedList<>(); 11 | private terminalStmt tailStmt = null; 12 | public block() {} 13 | public void push_back(statement stmt) { 14 | stmts.add(stmt); 15 | if (stmt instanceof terminalStmt) { 16 | if (tailStmt != null) 17 | throw new internalError("multiple tails of a block", 18 | new position(0, 0)); 19 | tailStmt = (terminalStmt)stmt; 20 | } 21 | } 22 | public ArrayList stmts() { 23 | return new ArrayList<>(stmts); 24 | } 25 | public ArrayList successors() { 26 | ArrayList ret = new ArrayList<>(); 27 | if (tailStmt instanceof branch) { 28 | ret.add(((branch) tailStmt).trueBranch); 29 | ret.add(((branch) tailStmt).falseBranch); 30 | } 31 | else if (tailStmt instanceof jump) { 32 | ret.add(((jump) tailStmt).destination); 33 | } 34 | return ret; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/MIR/branch.java: -------------------------------------------------------------------------------- 1 | package MIR; 2 | 3 | public class branch extends terminalStmt { 4 | public entity op; 5 | public block trueBranch, falseBranch; 6 | public branch(entity op, block trueBranch, block falseBranch) { 7 | super(); 8 | this.op = op; 9 | this.trueBranch = trueBranch; 10 | this.falseBranch = falseBranch; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/MIR/constant.java: -------------------------------------------------------------------------------- 1 | package MIR; 2 | 3 | public class constant extends entity{ 4 | private int value; 5 | public constant(int value) { 6 | super(); 7 | this.value = value; 8 | } 9 | public int value() { 10 | return value; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/MIR/entity.java: -------------------------------------------------------------------------------- 1 | package MIR; 2 | 3 | public class entity { 4 | } 5 | -------------------------------------------------------------------------------- /src/MIR/jump.java: -------------------------------------------------------------------------------- 1 | package MIR; 2 | 3 | public class jump extends terminalStmt { 4 | public block destination; 5 | public jump(block destination) { 6 | super(); 7 | this.destination = destination; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/MIR/mainFn.java: -------------------------------------------------------------------------------- 1 | package MIR; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | public class mainFn { 7 | public block rootBlock = new block(); 8 | public Set blocks = new HashSet<>(); 9 | 10 | public mainFn() { 11 | blocks.add(rootBlock); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/MIR/register.java: -------------------------------------------------------------------------------- 1 | package MIR; 2 | 3 | public class register extends entity { 4 | public register() { 5 | super(); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/MIR/ret.java: -------------------------------------------------------------------------------- 1 | package MIR; 2 | 3 | public class ret extends terminalStmt{ 4 | public entity value; 5 | public ret(entity value) { 6 | this.value = value; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/MIR/statement.java: -------------------------------------------------------------------------------- 1 | package MIR; 2 | 3 | public abstract class statement { 4 | public statement() {} 5 | } 6 | -------------------------------------------------------------------------------- /src/MIR/terminalStmt.java: -------------------------------------------------------------------------------- 1 | package MIR; 2 | 3 | public abstract class terminalStmt extends statement { 4 | } 5 | -------------------------------------------------------------------------------- /src/Main.java: -------------------------------------------------------------------------------- 1 | import AST.RootNode; 2 | import Assembly.AsmFn; 3 | import Backend.*; 4 | import Frontend.ASTBuilder; 5 | import Frontend.SemanticChecker; 6 | import Frontend.SymbolCollector; 7 | import MIR.block; 8 | import MIR.mainFn; 9 | import Parser.YxLexer; 10 | import Parser.YxParser; 11 | import Util.YxErrorListener; 12 | import Util.error.error; 13 | import Util.globalScope; 14 | import org.antlr.v4.runtime.CharStreams; 15 | import org.antlr.v4.runtime.CommonTokenStream; 16 | import org.antlr.v4.runtime.tree.ParseTree; 17 | 18 | import java.io.FileInputStream; 19 | import java.io.InputStream; 20 | 21 | 22 | public class Main { 23 | public static void main(String[] args) throws Exception{ 24 | 25 | String name = "test.yx"; 26 | InputStream input = new FileInputStream(name); 27 | 28 | try { 29 | RootNode ASTRoot; 30 | globalScope gScope = new globalScope(null); 31 | 32 | YxLexer lexer = new YxLexer(CharStreams.fromStream(input)); 33 | lexer.removeErrorListeners(); 34 | lexer.addErrorListener(new YxErrorListener()); 35 | YxParser parser = new YxParser(new CommonTokenStream(lexer)); 36 | parser.removeErrorListeners(); 37 | parser.addErrorListener(new YxErrorListener()); 38 | ParseTree parseTreeRoot = parser.program(); 39 | ASTBuilder astBuilder = new ASTBuilder(gScope); 40 | ASTRoot = (RootNode)astBuilder.visit(parseTreeRoot); 41 | new SymbolCollector(gScope).visit(ASTRoot); 42 | new SemanticChecker(gScope).visit(ASTRoot); 43 | 44 | mainFn f = new mainFn(); 45 | new IRBuilder(f, gScope).visit(ASTRoot); 46 | // new IRPrinter(System.out).visitFn(f); 47 | 48 | AsmFn asmF = new AsmFn(); 49 | new InstSelector(asmF).visitFn(f); 50 | new RegAlloc(asmF).work(); 51 | new AsmPrinter(asmF, System.out).print(); 52 | } catch (error er) { 53 | System.err.println(er.toString()); 54 | throw new RuntimeException(); 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /src/Parser/Yx.g4: -------------------------------------------------------------------------------- 1 | grammar Yx; 2 | 3 | program: classDef* mainFn; 4 | 5 | mainFn: 'int' 'main()' suite EOF; 6 | 7 | varDef : type Identifier ('=' expression)? ';'; 8 | classDef : 'struct' Identifier '{' varDef* '}'';'; 9 | 10 | suite : '{' statement* '}'; 11 | 12 | statement 13 | : suite #block 14 | | varDef #vardefStmt 15 | | If '(' expression ')' trueStmt=statement 16 | (Else falseStmt=statement)? #ifStmt 17 | | Return expression? ';' #returnStmt 18 | | expression ';' #pureExprStmt 19 | | ';' #emptyStmt 20 | ; 21 | 22 | expression 23 | : primary #atomExpr 24 | | expression op=('+' | '-') expression #binaryExpr 25 | | expression op=('==' | '!=' ) expression #binaryExpr 26 | | expression '=' expression #assignExpr 27 | ; 28 | 29 | primary 30 | : '(' expression ')' 31 | | Identifier 32 | | literal 33 | ; 34 | 35 | literal 36 | : DecimalInteger 37 | ; 38 | 39 | type : Int | Identifier; 40 | 41 | Int : 'int'; 42 | If : 'if'; 43 | Else : 'else'; 44 | Return : 'return'; 45 | Struct: 'struct'; 46 | 47 | LeftParen : '('; 48 | RightParen : ')'; 49 | LeftBracket : '['; 50 | RightBracket : ']'; 51 | LeftBrace : '{'; 52 | RightBrace : '}'; 53 | 54 | Less : '<'; 55 | LessEqual : '<='; 56 | Greater : '>'; 57 | GreaterEqual : '>='; 58 | LeftShift : '<<'; 59 | RightShift : '>>'; 60 | 61 | Plus : '+'; 62 | Minus : '-'; 63 | 64 | And : '&'; 65 | Or : '|'; 66 | AndAnd : '&&'; 67 | OrOr : '||'; 68 | Caret : '^'; 69 | Not : '!'; 70 | Tilde : '~'; 71 | 72 | Question : '?'; 73 | Colon : ':'; 74 | Semi : ';'; 75 | Comma : ','; 76 | 77 | Assign : '='; 78 | Equal : '=='; 79 | NotEqual : '!='; 80 | 81 | Identifier 82 | : [a-zA-Z] [a-zA-Z_0-9]* 83 | ; 84 | 85 | DecimalInteger 86 | : [1-9] [0-9]* 87 | | '0' 88 | ; 89 | 90 | Whitespace 91 | : [ \t]+ 92 | -> skip 93 | ; 94 | 95 | Newline 96 | : ( '\r' '\n'? 97 | | '\n' 98 | ) 99 | -> skip 100 | ; 101 | 102 | BlockComment 103 | : '/*' .*? '*/' 104 | -> skip 105 | ; 106 | 107 | LineComment 108 | : '//' ~[\r\n]* 109 | -> skip 110 | ; -------------------------------------------------------------------------------- /src/Parser/Yx.interp: -------------------------------------------------------------------------------- 1 | token literal names: 2 | null 3 | 'main()' 4 | 'int' 5 | 'if' 6 | 'else' 7 | 'return' 8 | 'struct' 9 | '(' 10 | ')' 11 | '[' 12 | ']' 13 | '{' 14 | '}' 15 | '<' 16 | '<=' 17 | '>' 18 | '>=' 19 | '<<' 20 | '>>' 21 | '+' 22 | '-' 23 | '&' 24 | '|' 25 | '&&' 26 | '||' 27 | '^' 28 | '!' 29 | '~' 30 | '?' 31 | ':' 32 | ';' 33 | ',' 34 | '=' 35 | '==' 36 | '!=' 37 | null 38 | null 39 | null 40 | null 41 | null 42 | null 43 | 44 | token symbolic names: 45 | null 46 | null 47 | Int 48 | If 49 | Else 50 | Return 51 | Struct 52 | LeftParen 53 | RightParen 54 | LeftBracket 55 | RightBracket 56 | LeftBrace 57 | RightBrace 58 | Less 59 | LessEqual 60 | Greater 61 | GreaterEqual 62 | LeftShift 63 | RightShift 64 | Plus 65 | Minus 66 | And 67 | Or 68 | AndAnd 69 | OrOr 70 | Caret 71 | Not 72 | Tilde 73 | Question 74 | Colon 75 | Semi 76 | Comma 77 | Assign 78 | Equal 79 | NotEqual 80 | Identifier 81 | DecimalInteger 82 | Whitespace 83 | Newline 84 | BlockComment 85 | LineComment 86 | 87 | rule names: 88 | program 89 | mainFn 90 | varDef 91 | classDef 92 | suite 93 | statement 94 | expression 95 | primary 96 | literal 97 | type 98 | 99 | 100 | atn: 101 | [3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 42, 116, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 3, 2, 7, 2, 24, 10, 2, 12, 2, 14, 2, 27, 11, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 4, 3, 4, 5, 4, 40, 10, 4, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 7, 5, 48, 10, 5, 12, 5, 14, 5, 51, 11, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 7, 6, 58, 10, 6, 12, 6, 14, 6, 61, 11, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 5, 7, 74, 10, 7, 3, 7, 3, 7, 5, 7, 78, 10, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 5, 7, 85, 10, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 7, 8, 99, 10, 8, 12, 8, 14, 8, 102, 11, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 5, 9, 110, 10, 9, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 2, 3, 14, 12, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 2, 5, 3, 2, 21, 22, 3, 2, 35, 36, 4, 2, 4, 4, 37, 37, 2, 121, 2, 25, 3, 2, 2, 2, 4, 30, 3, 2, 2, 2, 6, 35, 3, 2, 2, 2, 8, 43, 3, 2, 2, 2, 10, 55, 3, 2, 2, 2, 12, 84, 3, 2, 2, 2, 14, 86, 3, 2, 2, 2, 16, 109, 3, 2, 2, 2, 18, 111, 3, 2, 2, 2, 20, 113, 3, 2, 2, 2, 22, 24, 5, 8, 5, 2, 23, 22, 3, 2, 2, 2, 24, 27, 3, 2, 2, 2, 25, 23, 3, 2, 2, 2, 25, 26, 3, 2, 2, 2, 26, 28, 3, 2, 2, 2, 27, 25, 3, 2, 2, 2, 28, 29, 5, 4, 3, 2, 29, 3, 3, 2, 2, 2, 30, 31, 7, 4, 2, 2, 31, 32, 7, 3, 2, 2, 32, 33, 5, 10, 6, 2, 33, 34, 7, 2, 2, 3, 34, 5, 3, 2, 2, 2, 35, 36, 5, 20, 11, 2, 36, 39, 7, 37, 2, 2, 37, 38, 7, 34, 2, 2, 38, 40, 5, 14, 8, 2, 39, 37, 3, 2, 2, 2, 39, 40, 3, 2, 2, 2, 40, 41, 3, 2, 2, 2, 41, 42, 7, 32, 2, 2, 42, 7, 3, 2, 2, 2, 43, 44, 7, 8, 2, 2, 44, 45, 7, 37, 2, 2, 45, 49, 7, 13, 2, 2, 46, 48, 5, 6, 4, 2, 47, 46, 3, 2, 2, 2, 48, 51, 3, 2, 2, 2, 49, 47, 3, 2, 2, 2, 49, 50, 3, 2, 2, 2, 50, 52, 3, 2, 2, 2, 51, 49, 3, 2, 2, 2, 52, 53, 7, 14, 2, 2, 53, 54, 7, 32, 2, 2, 54, 9, 3, 2, 2, 2, 55, 59, 7, 13, 2, 2, 56, 58, 5, 12, 7, 2, 57, 56, 3, 2, 2, 2, 58, 61, 3, 2, 2, 2, 59, 57, 3, 2, 2, 2, 59, 60, 3, 2, 2, 2, 60, 62, 3, 2, 2, 2, 61, 59, 3, 2, 2, 2, 62, 63, 7, 14, 2, 2, 63, 11, 3, 2, 2, 2, 64, 85, 5, 10, 6, 2, 65, 85, 5, 6, 4, 2, 66, 67, 7, 5, 2, 2, 67, 68, 7, 9, 2, 2, 68, 69, 5, 14, 8, 2, 69, 70, 7, 10, 2, 2, 70, 73, 5, 12, 7, 2, 71, 72, 7, 6, 2, 2, 72, 74, 5, 12, 7, 2, 73, 71, 3, 2, 2, 2, 73, 74, 3, 2, 2, 2, 74, 85, 3, 2, 2, 2, 75, 77, 7, 7, 2, 2, 76, 78, 5, 14, 8, 2, 77, 76, 3, 2, 2, 2, 77, 78, 3, 2, 2, 2, 78, 79, 3, 2, 2, 2, 79, 85, 7, 32, 2, 2, 80, 81, 5, 14, 8, 2, 81, 82, 7, 32, 2, 2, 82, 85, 3, 2, 2, 2, 83, 85, 7, 32, 2, 2, 84, 64, 3, 2, 2, 2, 84, 65, 3, 2, 2, 2, 84, 66, 3, 2, 2, 2, 84, 75, 3, 2, 2, 2, 84, 80, 3, 2, 2, 2, 84, 83, 3, 2, 2, 2, 85, 13, 3, 2, 2, 2, 86, 87, 8, 8, 1, 2, 87, 88, 5, 16, 9, 2, 88, 100, 3, 2, 2, 2, 89, 90, 12, 5, 2, 2, 90, 91, 9, 2, 2, 2, 91, 99, 5, 14, 8, 6, 92, 93, 12, 4, 2, 2, 93, 94, 9, 3, 2, 2, 94, 99, 5, 14, 8, 5, 95, 96, 12, 3, 2, 2, 96, 97, 7, 34, 2, 2, 97, 99, 5, 14, 8, 3, 98, 89, 3, 2, 2, 2, 98, 92, 3, 2, 2, 2, 98, 95, 3, 2, 2, 2, 99, 102, 3, 2, 2, 2, 100, 98, 3, 2, 2, 2, 100, 101, 3, 2, 2, 2, 101, 15, 3, 2, 2, 2, 102, 100, 3, 2, 2, 2, 103, 104, 7, 9, 2, 2, 104, 105, 5, 14, 8, 2, 105, 106, 7, 10, 2, 2, 106, 110, 3, 2, 2, 2, 107, 110, 7, 37, 2, 2, 108, 110, 5, 18, 10, 2, 109, 103, 3, 2, 2, 2, 109, 107, 3, 2, 2, 2, 109, 108, 3, 2, 2, 2, 110, 17, 3, 2, 2, 2, 111, 112, 7, 38, 2, 2, 112, 19, 3, 2, 2, 2, 113, 114, 9, 4, 2, 2, 114, 21, 3, 2, 2, 2, 12, 25, 39, 49, 59, 73, 77, 84, 98, 100, 109] -------------------------------------------------------------------------------- /src/Parser/Yx.tokens: -------------------------------------------------------------------------------- 1 | T__0=1 2 | Int=2 3 | If=3 4 | Else=4 5 | Return=5 6 | Struct=6 7 | LeftParen=7 8 | RightParen=8 9 | LeftBracket=9 10 | RightBracket=10 11 | LeftBrace=11 12 | RightBrace=12 13 | Less=13 14 | LessEqual=14 15 | Greater=15 16 | GreaterEqual=16 17 | LeftShift=17 18 | RightShift=18 19 | Plus=19 20 | Minus=20 21 | And=21 22 | Or=22 23 | AndAnd=23 24 | OrOr=24 25 | Caret=25 26 | Not=26 27 | Tilde=27 28 | Question=28 29 | Colon=29 30 | Semi=30 31 | Comma=31 32 | Assign=32 33 | Equal=33 34 | NotEqual=34 35 | Identifier=35 36 | DecimalInteger=36 37 | Whitespace=37 38 | Newline=38 39 | BlockComment=39 40 | LineComment=40 41 | 'main()'=1 42 | 'int'=2 43 | 'if'=3 44 | 'else'=4 45 | 'return'=5 46 | 'struct'=6 47 | '('=7 48 | ')'=8 49 | '['=9 50 | ']'=10 51 | '{'=11 52 | '}'=12 53 | '<'=13 54 | '<='=14 55 | '>'=15 56 | '>='=16 57 | '<<'=17 58 | '>>'=18 59 | '+'=19 60 | '-'=20 61 | '&'=21 62 | '|'=22 63 | '&&'=23 64 | '||'=24 65 | '^'=25 66 | '!'=26 67 | '~'=27 68 | '?'=28 69 | ':'=29 70 | ';'=30 71 | ','=31 72 | '='=32 73 | '=='=33 74 | '!='=34 75 | -------------------------------------------------------------------------------- /src/Parser/YxBaseListener.java: -------------------------------------------------------------------------------- 1 | // Generated from Yx.g4 by ANTLR 4.7.2 2 | package Parser; 3 | import org.antlr.v4.runtime.ParserRuleContext; 4 | import org.antlr.v4.runtime.tree.ErrorNode; 5 | import org.antlr.v4.runtime.tree.TerminalNode; 6 | 7 | /** 8 | * This class provides an empty implementation of {@link YxListener}, 9 | * which can be extended to create a listener which only needs to handle a subset 10 | * of the available methods. 11 | */ 12 | public class YxBaseListener implements YxListener { 13 | /** 14 | * {@inheritDoc} 15 | * 16 | *

The default implementation does nothing.

17 | */ 18 | @Override public void enterProgram(YxParser.ProgramContext ctx) { } 19 | /** 20 | * {@inheritDoc} 21 | * 22 | *

The default implementation does nothing.

23 | */ 24 | @Override public void exitProgram(YxParser.ProgramContext ctx) { } 25 | /** 26 | * {@inheritDoc} 27 | * 28 | *

The default implementation does nothing.

29 | */ 30 | @Override public void enterMainFn(YxParser.MainFnContext ctx) { } 31 | /** 32 | * {@inheritDoc} 33 | * 34 | *

The default implementation does nothing.

35 | */ 36 | @Override public void exitMainFn(YxParser.MainFnContext ctx) { } 37 | /** 38 | * {@inheritDoc} 39 | * 40 | *

The default implementation does nothing.

41 | */ 42 | @Override public void enterVarDef(YxParser.VarDefContext ctx) { } 43 | /** 44 | * {@inheritDoc} 45 | * 46 | *

The default implementation does nothing.

47 | */ 48 | @Override public void exitVarDef(YxParser.VarDefContext ctx) { } 49 | /** 50 | * {@inheritDoc} 51 | * 52 | *

The default implementation does nothing.

53 | */ 54 | @Override public void enterClassDef(YxParser.ClassDefContext ctx) { } 55 | /** 56 | * {@inheritDoc} 57 | * 58 | *

The default implementation does nothing.

59 | */ 60 | @Override public void exitClassDef(YxParser.ClassDefContext ctx) { } 61 | /** 62 | * {@inheritDoc} 63 | * 64 | *

The default implementation does nothing.

65 | */ 66 | @Override public void enterSuite(YxParser.SuiteContext ctx) { } 67 | /** 68 | * {@inheritDoc} 69 | * 70 | *

The default implementation does nothing.

71 | */ 72 | @Override public void exitSuite(YxParser.SuiteContext ctx) { } 73 | /** 74 | * {@inheritDoc} 75 | * 76 | *

The default implementation does nothing.

77 | */ 78 | @Override public void enterBlock(YxParser.BlockContext ctx) { } 79 | /** 80 | * {@inheritDoc} 81 | * 82 | *

The default implementation does nothing.

83 | */ 84 | @Override public void exitBlock(YxParser.BlockContext ctx) { } 85 | /** 86 | * {@inheritDoc} 87 | * 88 | *

The default implementation does nothing.

89 | */ 90 | @Override public void enterVardefStmt(YxParser.VardefStmtContext ctx) { } 91 | /** 92 | * {@inheritDoc} 93 | * 94 | *

The default implementation does nothing.

95 | */ 96 | @Override public void exitVardefStmt(YxParser.VardefStmtContext ctx) { } 97 | /** 98 | * {@inheritDoc} 99 | * 100 | *

The default implementation does nothing.

101 | */ 102 | @Override public void enterIfStmt(YxParser.IfStmtContext ctx) { } 103 | /** 104 | * {@inheritDoc} 105 | * 106 | *

The default implementation does nothing.

107 | */ 108 | @Override public void exitIfStmt(YxParser.IfStmtContext ctx) { } 109 | /** 110 | * {@inheritDoc} 111 | * 112 | *

The default implementation does nothing.

113 | */ 114 | @Override public void enterReturnStmt(YxParser.ReturnStmtContext ctx) { } 115 | /** 116 | * {@inheritDoc} 117 | * 118 | *

The default implementation does nothing.

119 | */ 120 | @Override public void exitReturnStmt(YxParser.ReturnStmtContext ctx) { } 121 | /** 122 | * {@inheritDoc} 123 | * 124 | *

The default implementation does nothing.

125 | */ 126 | @Override public void enterPureExprStmt(YxParser.PureExprStmtContext ctx) { } 127 | /** 128 | * {@inheritDoc} 129 | * 130 | *

The default implementation does nothing.

131 | */ 132 | @Override public void exitPureExprStmt(YxParser.PureExprStmtContext ctx) { } 133 | /** 134 | * {@inheritDoc} 135 | * 136 | *

The default implementation does nothing.

137 | */ 138 | @Override public void enterEmptyStmt(YxParser.EmptyStmtContext ctx) { } 139 | /** 140 | * {@inheritDoc} 141 | * 142 | *

The default implementation does nothing.

143 | */ 144 | @Override public void exitEmptyStmt(YxParser.EmptyStmtContext ctx) { } 145 | /** 146 | * {@inheritDoc} 147 | * 148 | *

The default implementation does nothing.

149 | */ 150 | @Override public void enterAtomExpr(YxParser.AtomExprContext ctx) { } 151 | /** 152 | * {@inheritDoc} 153 | * 154 | *

The default implementation does nothing.

155 | */ 156 | @Override public void exitAtomExpr(YxParser.AtomExprContext ctx) { } 157 | /** 158 | * {@inheritDoc} 159 | * 160 | *

The default implementation does nothing.

161 | */ 162 | @Override public void enterBinaryExpr(YxParser.BinaryExprContext ctx) { } 163 | /** 164 | * {@inheritDoc} 165 | * 166 | *

The default implementation does nothing.

167 | */ 168 | @Override public void exitBinaryExpr(YxParser.BinaryExprContext ctx) { } 169 | /** 170 | * {@inheritDoc} 171 | * 172 | *

The default implementation does nothing.

173 | */ 174 | @Override public void enterAssignExpr(YxParser.AssignExprContext ctx) { } 175 | /** 176 | * {@inheritDoc} 177 | * 178 | *

The default implementation does nothing.

179 | */ 180 | @Override public void exitAssignExpr(YxParser.AssignExprContext ctx) { } 181 | /** 182 | * {@inheritDoc} 183 | * 184 | *

The default implementation does nothing.

185 | */ 186 | @Override public void enterPrimary(YxParser.PrimaryContext ctx) { } 187 | /** 188 | * {@inheritDoc} 189 | * 190 | *

The default implementation does nothing.

191 | */ 192 | @Override public void exitPrimary(YxParser.PrimaryContext ctx) { } 193 | /** 194 | * {@inheritDoc} 195 | * 196 | *

The default implementation does nothing.

197 | */ 198 | @Override public void enterLiteral(YxParser.LiteralContext ctx) { } 199 | /** 200 | * {@inheritDoc} 201 | * 202 | *

The default implementation does nothing.

203 | */ 204 | @Override public void exitLiteral(YxParser.LiteralContext ctx) { } 205 | /** 206 | * {@inheritDoc} 207 | * 208 | *

The default implementation does nothing.

209 | */ 210 | @Override public void enterType(YxParser.TypeContext ctx) { } 211 | /** 212 | * {@inheritDoc} 213 | * 214 | *

The default implementation does nothing.

215 | */ 216 | @Override public void exitType(YxParser.TypeContext ctx) { } 217 | 218 | /** 219 | * {@inheritDoc} 220 | * 221 | *

The default implementation does nothing.

222 | */ 223 | @Override public void enterEveryRule(ParserRuleContext ctx) { } 224 | /** 225 | * {@inheritDoc} 226 | * 227 | *

The default implementation does nothing.

228 | */ 229 | @Override public void exitEveryRule(ParserRuleContext ctx) { } 230 | /** 231 | * {@inheritDoc} 232 | * 233 | *

The default implementation does nothing.

234 | */ 235 | @Override public void visitTerminal(TerminalNode node) { } 236 | /** 237 | * {@inheritDoc} 238 | * 239 | *

The default implementation does nothing.

240 | */ 241 | @Override public void visitErrorNode(ErrorNode node) { } 242 | } -------------------------------------------------------------------------------- /src/Parser/YxBaseVisitor.java: -------------------------------------------------------------------------------- 1 | // Generated from Yx.g4 by ANTLR 4.7.2 2 | package Parser; 3 | import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor; 4 | 5 | /** 6 | * This class provides an empty implementation of {@link YxVisitor}, 7 | * which can be extended to create a visitor which only needs to handle a subset 8 | * of the available methods. 9 | * 10 | * @param The return type of the visit operation. Use {@link Void} for 11 | * operations with no return type. 12 | */ 13 | public class YxBaseVisitor extends AbstractParseTreeVisitor implements YxVisitor { 14 | /** 15 | * {@inheritDoc} 16 | * 17 | *

The default implementation returns the result of calling 18 | * {@link #visitChildren} on {@code ctx}.

19 | */ 20 | @Override public T visitProgram(YxParser.ProgramContext ctx) { return visitChildren(ctx); } 21 | /** 22 | * {@inheritDoc} 23 | * 24 | *

The default implementation returns the result of calling 25 | * {@link #visitChildren} on {@code ctx}.

26 | */ 27 | @Override public T visitMainFn(YxParser.MainFnContext ctx) { return visitChildren(ctx); } 28 | /** 29 | * {@inheritDoc} 30 | * 31 | *

The default implementation returns the result of calling 32 | * {@link #visitChildren} on {@code ctx}.

33 | */ 34 | @Override public T visitVarDef(YxParser.VarDefContext ctx) { return visitChildren(ctx); } 35 | /** 36 | * {@inheritDoc} 37 | * 38 | *

The default implementation returns the result of calling 39 | * {@link #visitChildren} on {@code ctx}.

40 | */ 41 | @Override public T visitClassDef(YxParser.ClassDefContext ctx) { return visitChildren(ctx); } 42 | /** 43 | * {@inheritDoc} 44 | * 45 | *

The default implementation returns the result of calling 46 | * {@link #visitChildren} on {@code ctx}.

47 | */ 48 | @Override public T visitSuite(YxParser.SuiteContext ctx) { return visitChildren(ctx); } 49 | /** 50 | * {@inheritDoc} 51 | * 52 | *

The default implementation returns the result of calling 53 | * {@link #visitChildren} on {@code ctx}.

54 | */ 55 | @Override public T visitBlock(YxParser.BlockContext ctx) { return visitChildren(ctx); } 56 | /** 57 | * {@inheritDoc} 58 | * 59 | *

The default implementation returns the result of calling 60 | * {@link #visitChildren} on {@code ctx}.

61 | */ 62 | @Override public T visitVardefStmt(YxParser.VardefStmtContext ctx) { return visitChildren(ctx); } 63 | /** 64 | * {@inheritDoc} 65 | * 66 | *

The default implementation returns the result of calling 67 | * {@link #visitChildren} on {@code ctx}.

68 | */ 69 | @Override public T visitIfStmt(YxParser.IfStmtContext ctx) { return visitChildren(ctx); } 70 | /** 71 | * {@inheritDoc} 72 | * 73 | *

The default implementation returns the result of calling 74 | * {@link #visitChildren} on {@code ctx}.

75 | */ 76 | @Override public T visitReturnStmt(YxParser.ReturnStmtContext ctx) { return visitChildren(ctx); } 77 | /** 78 | * {@inheritDoc} 79 | * 80 | *

The default implementation returns the result of calling 81 | * {@link #visitChildren} on {@code ctx}.

82 | */ 83 | @Override public T visitPureExprStmt(YxParser.PureExprStmtContext ctx) { return visitChildren(ctx); } 84 | /** 85 | * {@inheritDoc} 86 | * 87 | *

The default implementation returns the result of calling 88 | * {@link #visitChildren} on {@code ctx}.

89 | */ 90 | @Override public T visitEmptyStmt(YxParser.EmptyStmtContext ctx) { return visitChildren(ctx); } 91 | /** 92 | * {@inheritDoc} 93 | * 94 | *

The default implementation returns the result of calling 95 | * {@link #visitChildren} on {@code ctx}.

96 | */ 97 | @Override public T visitAtomExpr(YxParser.AtomExprContext ctx) { return visitChildren(ctx); } 98 | /** 99 | * {@inheritDoc} 100 | * 101 | *

The default implementation returns the result of calling 102 | * {@link #visitChildren} on {@code ctx}.

103 | */ 104 | @Override public T visitBinaryExpr(YxParser.BinaryExprContext ctx) { return visitChildren(ctx); } 105 | /** 106 | * {@inheritDoc} 107 | * 108 | *

The default implementation returns the result of calling 109 | * {@link #visitChildren} on {@code ctx}.

110 | */ 111 | @Override public T visitAssignExpr(YxParser.AssignExprContext ctx) { return visitChildren(ctx); } 112 | /** 113 | * {@inheritDoc} 114 | * 115 | *

The default implementation returns the result of calling 116 | * {@link #visitChildren} on {@code ctx}.

117 | */ 118 | @Override public T visitPrimary(YxParser.PrimaryContext ctx) { return visitChildren(ctx); } 119 | /** 120 | * {@inheritDoc} 121 | * 122 | *

The default implementation returns the result of calling 123 | * {@link #visitChildren} on {@code ctx}.

124 | */ 125 | @Override public T visitLiteral(YxParser.LiteralContext ctx) { return visitChildren(ctx); } 126 | /** 127 | * {@inheritDoc} 128 | * 129 | *

The default implementation returns the result of calling 130 | * {@link #visitChildren} on {@code ctx}.

131 | */ 132 | @Override public T visitType(YxParser.TypeContext ctx) { return visitChildren(ctx); } 133 | } -------------------------------------------------------------------------------- /src/Parser/YxLexer.interp: -------------------------------------------------------------------------------- 1 | token literal names: 2 | null 3 | 'main()' 4 | 'int' 5 | 'if' 6 | 'else' 7 | 'return' 8 | 'struct' 9 | '(' 10 | ')' 11 | '[' 12 | ']' 13 | '{' 14 | '}' 15 | '<' 16 | '<=' 17 | '>' 18 | '>=' 19 | '<<' 20 | '>>' 21 | '+' 22 | '-' 23 | '&' 24 | '|' 25 | '&&' 26 | '||' 27 | '^' 28 | '!' 29 | '~' 30 | '?' 31 | ':' 32 | ';' 33 | ',' 34 | '=' 35 | '==' 36 | '!=' 37 | null 38 | null 39 | null 40 | null 41 | null 42 | null 43 | 44 | token symbolic names: 45 | null 46 | null 47 | Int 48 | If 49 | Else 50 | Return 51 | Struct 52 | LeftParen 53 | RightParen 54 | LeftBracket 55 | RightBracket 56 | LeftBrace 57 | RightBrace 58 | Less 59 | LessEqual 60 | Greater 61 | GreaterEqual 62 | LeftShift 63 | RightShift 64 | Plus 65 | Minus 66 | And 67 | Or 68 | AndAnd 69 | OrOr 70 | Caret 71 | Not 72 | Tilde 73 | Question 74 | Colon 75 | Semi 76 | Comma 77 | Assign 78 | Equal 79 | NotEqual 80 | Identifier 81 | DecimalInteger 82 | Whitespace 83 | Newline 84 | BlockComment 85 | LineComment 86 | 87 | rule names: 88 | T__0 89 | Int 90 | If 91 | Else 92 | Return 93 | Struct 94 | LeftParen 95 | RightParen 96 | LeftBracket 97 | RightBracket 98 | LeftBrace 99 | RightBrace 100 | Less 101 | LessEqual 102 | Greater 103 | GreaterEqual 104 | LeftShift 105 | RightShift 106 | Plus 107 | Minus 108 | And 109 | Or 110 | AndAnd 111 | OrOr 112 | Caret 113 | Not 114 | Tilde 115 | Question 116 | Colon 117 | Semi 118 | Comma 119 | Assign 120 | Equal 121 | NotEqual 122 | Identifier 123 | DecimalInteger 124 | Whitespace 125 | Newline 126 | BlockComment 127 | LineComment 128 | 129 | channel names: 130 | DEFAULT_TOKEN_CHANNEL 131 | HIDDEN 132 | 133 | mode names: 134 | DEFAULT_MODE 135 | 136 | atn: 137 | [3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 42, 238, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 3, 12, 3, 12, 3, 13, 3, 13, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 19, 3, 19, 3, 19, 3, 20, 3, 20, 3, 21, 3, 21, 3, 22, 3, 22, 3, 23, 3, 23, 3, 24, 3, 24, 3, 24, 3, 25, 3, 25, 3, 25, 3, 26, 3, 26, 3, 27, 3, 27, 3, 28, 3, 28, 3, 29, 3, 29, 3, 30, 3, 30, 3, 31, 3, 31, 3, 32, 3, 32, 3, 33, 3, 33, 3, 34, 3, 34, 3, 34, 3, 35, 3, 35, 3, 35, 3, 36, 3, 36, 7, 36, 183, 10, 36, 12, 36, 14, 36, 186, 11, 36, 3, 37, 3, 37, 7, 37, 190, 10, 37, 12, 37, 14, 37, 193, 11, 37, 3, 37, 5, 37, 196, 10, 37, 3, 38, 6, 38, 199, 10, 38, 13, 38, 14, 38, 200, 3, 38, 3, 38, 3, 39, 3, 39, 5, 39, 207, 10, 39, 3, 39, 5, 39, 210, 10, 39, 3, 39, 3, 39, 3, 40, 3, 40, 3, 40, 3, 40, 7, 40, 218, 10, 40, 12, 40, 14, 40, 221, 11, 40, 3, 40, 3, 40, 3, 40, 3, 40, 3, 40, 3, 41, 3, 41, 3, 41, 3, 41, 7, 41, 232, 10, 41, 12, 41, 14, 41, 235, 11, 41, 3, 41, 3, 41, 3, 219, 2, 42, 3, 3, 5, 4, 7, 5, 9, 6, 11, 7, 13, 8, 15, 9, 17, 10, 19, 11, 21, 12, 23, 13, 25, 14, 27, 15, 29, 16, 31, 17, 33, 18, 35, 19, 37, 20, 39, 21, 41, 22, 43, 23, 45, 24, 47, 25, 49, 26, 51, 27, 53, 28, 55, 29, 57, 30, 59, 31, 61, 32, 63, 33, 65, 34, 67, 35, 69, 36, 71, 37, 73, 38, 75, 39, 77, 40, 79, 41, 81, 42, 3, 2, 8, 4, 2, 67, 92, 99, 124, 6, 2, 50, 59, 67, 92, 97, 97, 99, 124, 3, 2, 51, 59, 3, 2, 50, 59, 4, 2, 11, 11, 34, 34, 4, 2, 12, 12, 15, 15, 2, 245, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 31, 3, 2, 2, 2, 2, 33, 3, 2, 2, 2, 2, 35, 3, 2, 2, 2, 2, 37, 3, 2, 2, 2, 2, 39, 3, 2, 2, 2, 2, 41, 3, 2, 2, 2, 2, 43, 3, 2, 2, 2, 2, 45, 3, 2, 2, 2, 2, 47, 3, 2, 2, 2, 2, 49, 3, 2, 2, 2, 2, 51, 3, 2, 2, 2, 2, 53, 3, 2, 2, 2, 2, 55, 3, 2, 2, 2, 2, 57, 3, 2, 2, 2, 2, 59, 3, 2, 2, 2, 2, 61, 3, 2, 2, 2, 2, 63, 3, 2, 2, 2, 2, 65, 3, 2, 2, 2, 2, 67, 3, 2, 2, 2, 2, 69, 3, 2, 2, 2, 2, 71, 3, 2, 2, 2, 2, 73, 3, 2, 2, 2, 2, 75, 3, 2, 2, 2, 2, 77, 3, 2, 2, 2, 2, 79, 3, 2, 2, 2, 2, 81, 3, 2, 2, 2, 3, 83, 3, 2, 2, 2, 5, 90, 3, 2, 2, 2, 7, 94, 3, 2, 2, 2, 9, 97, 3, 2, 2, 2, 11, 102, 3, 2, 2, 2, 13, 109, 3, 2, 2, 2, 15, 116, 3, 2, 2, 2, 17, 118, 3, 2, 2, 2, 19, 120, 3, 2, 2, 2, 21, 122, 3, 2, 2, 2, 23, 124, 3, 2, 2, 2, 25, 126, 3, 2, 2, 2, 27, 128, 3, 2, 2, 2, 29, 130, 3, 2, 2, 2, 31, 133, 3, 2, 2, 2, 33, 135, 3, 2, 2, 2, 35, 138, 3, 2, 2, 2, 37, 141, 3, 2, 2, 2, 39, 144, 3, 2, 2, 2, 41, 146, 3, 2, 2, 2, 43, 148, 3, 2, 2, 2, 45, 150, 3, 2, 2, 2, 47, 152, 3, 2, 2, 2, 49, 155, 3, 2, 2, 2, 51, 158, 3, 2, 2, 2, 53, 160, 3, 2, 2, 2, 55, 162, 3, 2, 2, 2, 57, 164, 3, 2, 2, 2, 59, 166, 3, 2, 2, 2, 61, 168, 3, 2, 2, 2, 63, 170, 3, 2, 2, 2, 65, 172, 3, 2, 2, 2, 67, 174, 3, 2, 2, 2, 69, 177, 3, 2, 2, 2, 71, 180, 3, 2, 2, 2, 73, 195, 3, 2, 2, 2, 75, 198, 3, 2, 2, 2, 77, 209, 3, 2, 2, 2, 79, 213, 3, 2, 2, 2, 81, 227, 3, 2, 2, 2, 83, 84, 7, 111, 2, 2, 84, 85, 7, 99, 2, 2, 85, 86, 7, 107, 2, 2, 86, 87, 7, 112, 2, 2, 87, 88, 7, 42, 2, 2, 88, 89, 7, 43, 2, 2, 89, 4, 3, 2, 2, 2, 90, 91, 7, 107, 2, 2, 91, 92, 7, 112, 2, 2, 92, 93, 7, 118, 2, 2, 93, 6, 3, 2, 2, 2, 94, 95, 7, 107, 2, 2, 95, 96, 7, 104, 2, 2, 96, 8, 3, 2, 2, 2, 97, 98, 7, 103, 2, 2, 98, 99, 7, 110, 2, 2, 99, 100, 7, 117, 2, 2, 100, 101, 7, 103, 2, 2, 101, 10, 3, 2, 2, 2, 102, 103, 7, 116, 2, 2, 103, 104, 7, 103, 2, 2, 104, 105, 7, 118, 2, 2, 105, 106, 7, 119, 2, 2, 106, 107, 7, 116, 2, 2, 107, 108, 7, 112, 2, 2, 108, 12, 3, 2, 2, 2, 109, 110, 7, 117, 2, 2, 110, 111, 7, 118, 2, 2, 111, 112, 7, 116, 2, 2, 112, 113, 7, 119, 2, 2, 113, 114, 7, 101, 2, 2, 114, 115, 7, 118, 2, 2, 115, 14, 3, 2, 2, 2, 116, 117, 7, 42, 2, 2, 117, 16, 3, 2, 2, 2, 118, 119, 7, 43, 2, 2, 119, 18, 3, 2, 2, 2, 120, 121, 7, 93, 2, 2, 121, 20, 3, 2, 2, 2, 122, 123, 7, 95, 2, 2, 123, 22, 3, 2, 2, 2, 124, 125, 7, 125, 2, 2, 125, 24, 3, 2, 2, 2, 126, 127, 7, 127, 2, 2, 127, 26, 3, 2, 2, 2, 128, 129, 7, 62, 2, 2, 129, 28, 3, 2, 2, 2, 130, 131, 7, 62, 2, 2, 131, 132, 7, 63, 2, 2, 132, 30, 3, 2, 2, 2, 133, 134, 7, 64, 2, 2, 134, 32, 3, 2, 2, 2, 135, 136, 7, 64, 2, 2, 136, 137, 7, 63, 2, 2, 137, 34, 3, 2, 2, 2, 138, 139, 7, 62, 2, 2, 139, 140, 7, 62, 2, 2, 140, 36, 3, 2, 2, 2, 141, 142, 7, 64, 2, 2, 142, 143, 7, 64, 2, 2, 143, 38, 3, 2, 2, 2, 144, 145, 7, 45, 2, 2, 145, 40, 3, 2, 2, 2, 146, 147, 7, 47, 2, 2, 147, 42, 3, 2, 2, 2, 148, 149, 7, 40, 2, 2, 149, 44, 3, 2, 2, 2, 150, 151, 7, 126, 2, 2, 151, 46, 3, 2, 2, 2, 152, 153, 7, 40, 2, 2, 153, 154, 7, 40, 2, 2, 154, 48, 3, 2, 2, 2, 155, 156, 7, 126, 2, 2, 156, 157, 7, 126, 2, 2, 157, 50, 3, 2, 2, 2, 158, 159, 7, 96, 2, 2, 159, 52, 3, 2, 2, 2, 160, 161, 7, 35, 2, 2, 161, 54, 3, 2, 2, 2, 162, 163, 7, 128, 2, 2, 163, 56, 3, 2, 2, 2, 164, 165, 7, 65, 2, 2, 165, 58, 3, 2, 2, 2, 166, 167, 7, 60, 2, 2, 167, 60, 3, 2, 2, 2, 168, 169, 7, 61, 2, 2, 169, 62, 3, 2, 2, 2, 170, 171, 7, 46, 2, 2, 171, 64, 3, 2, 2, 2, 172, 173, 7, 63, 2, 2, 173, 66, 3, 2, 2, 2, 174, 175, 7, 63, 2, 2, 175, 176, 7, 63, 2, 2, 176, 68, 3, 2, 2, 2, 177, 178, 7, 35, 2, 2, 178, 179, 7, 63, 2, 2, 179, 70, 3, 2, 2, 2, 180, 184, 9, 2, 2, 2, 181, 183, 9, 3, 2, 2, 182, 181, 3, 2, 2, 2, 183, 186, 3, 2, 2, 2, 184, 182, 3, 2, 2, 2, 184, 185, 3, 2, 2, 2, 185, 72, 3, 2, 2, 2, 186, 184, 3, 2, 2, 2, 187, 191, 9, 4, 2, 2, 188, 190, 9, 5, 2, 2, 189, 188, 3, 2, 2, 2, 190, 193, 3, 2, 2, 2, 191, 189, 3, 2, 2, 2, 191, 192, 3, 2, 2, 2, 192, 196, 3, 2, 2, 2, 193, 191, 3, 2, 2, 2, 194, 196, 7, 50, 2, 2, 195, 187, 3, 2, 2, 2, 195, 194, 3, 2, 2, 2, 196, 74, 3, 2, 2, 2, 197, 199, 9, 6, 2, 2, 198, 197, 3, 2, 2, 2, 199, 200, 3, 2, 2, 2, 200, 198, 3, 2, 2, 2, 200, 201, 3, 2, 2, 2, 201, 202, 3, 2, 2, 2, 202, 203, 8, 38, 2, 2, 203, 76, 3, 2, 2, 2, 204, 206, 7, 15, 2, 2, 205, 207, 7, 12, 2, 2, 206, 205, 3, 2, 2, 2, 206, 207, 3, 2, 2, 2, 207, 210, 3, 2, 2, 2, 208, 210, 7, 12, 2, 2, 209, 204, 3, 2, 2, 2, 209, 208, 3, 2, 2, 2, 210, 211, 3, 2, 2, 2, 211, 212, 8, 39, 2, 2, 212, 78, 3, 2, 2, 2, 213, 214, 7, 49, 2, 2, 214, 215, 7, 44, 2, 2, 215, 219, 3, 2, 2, 2, 216, 218, 11, 2, 2, 2, 217, 216, 3, 2, 2, 2, 218, 221, 3, 2, 2, 2, 219, 220, 3, 2, 2, 2, 219, 217, 3, 2, 2, 2, 220, 222, 3, 2, 2, 2, 221, 219, 3, 2, 2, 2, 222, 223, 7, 44, 2, 2, 223, 224, 7, 49, 2, 2, 224, 225, 3, 2, 2, 2, 225, 226, 8, 40, 2, 2, 226, 80, 3, 2, 2, 2, 227, 228, 7, 49, 2, 2, 228, 229, 7, 49, 2, 2, 229, 233, 3, 2, 2, 2, 230, 232, 10, 7, 2, 2, 231, 230, 3, 2, 2, 2, 232, 235, 3, 2, 2, 2, 233, 231, 3, 2, 2, 2, 233, 234, 3, 2, 2, 2, 234, 236, 3, 2, 2, 2, 235, 233, 3, 2, 2, 2, 236, 237, 8, 41, 2, 2, 237, 82, 3, 2, 2, 2, 11, 2, 184, 191, 195, 200, 206, 209, 219, 233, 3, 8, 2, 2] -------------------------------------------------------------------------------- /src/Parser/YxLexer.java: -------------------------------------------------------------------------------- 1 | // Generated from Yx.g4 by ANTLR 4.7.2 2 | package Parser; 3 | import org.antlr.v4.runtime.Lexer; 4 | import org.antlr.v4.runtime.CharStream; 5 | import org.antlr.v4.runtime.Token; 6 | import org.antlr.v4.runtime.TokenStream; 7 | import org.antlr.v4.runtime.*; 8 | import org.antlr.v4.runtime.atn.*; 9 | import org.antlr.v4.runtime.dfa.DFA; 10 | import org.antlr.v4.runtime.misc.*; 11 | 12 | @SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) 13 | public class YxLexer extends Lexer { 14 | static { RuntimeMetaData.checkVersion("4.7.2", RuntimeMetaData.VERSION); } 15 | 16 | protected static final DFA[] _decisionToDFA; 17 | protected static final PredictionContextCache _sharedContextCache = 18 | new PredictionContextCache(); 19 | public static final int 20 | T__0=1, Int=2, If=3, Else=4, Return=5, Struct=6, LeftParen=7, RightParen=8, 21 | LeftBracket=9, RightBracket=10, LeftBrace=11, RightBrace=12, Less=13, 22 | LessEqual=14, Greater=15, GreaterEqual=16, LeftShift=17, RightShift=18, 23 | Plus=19, Minus=20, And=21, Or=22, AndAnd=23, OrOr=24, Caret=25, Not=26, 24 | Tilde=27, Question=28, Colon=29, Semi=30, Comma=31, Assign=32, Equal=33, 25 | NotEqual=34, Identifier=35, DecimalInteger=36, Whitespace=37, Newline=38, 26 | BlockComment=39, LineComment=40; 27 | public static String[] channelNames = { 28 | "DEFAULT_TOKEN_CHANNEL", "HIDDEN" 29 | }; 30 | 31 | public static String[] modeNames = { 32 | "DEFAULT_MODE" 33 | }; 34 | 35 | private static String[] makeRuleNames() { 36 | return new String[] { 37 | "T__0", "Int", "If", "Else", "Return", "Struct", "LeftParen", "RightParen", 38 | "LeftBracket", "RightBracket", "LeftBrace", "RightBrace", "Less", "LessEqual", 39 | "Greater", "GreaterEqual", "LeftShift", "RightShift", "Plus", "Minus", 40 | "And", "Or", "AndAnd", "OrOr", "Caret", "Not", "Tilde", "Question", "Colon", 41 | "Semi", "Comma", "Assign", "Equal", "NotEqual", "Identifier", "DecimalInteger", 42 | "Whitespace", "Newline", "BlockComment", "LineComment" 43 | }; 44 | } 45 | public static final String[] ruleNames = makeRuleNames(); 46 | 47 | private static String[] makeLiteralNames() { 48 | return new String[] { 49 | null, "'main()'", "'int'", "'if'", "'else'", "'return'", "'struct'", 50 | "'('", "')'", "'['", "']'", "'{'", "'}'", "'<'", "'<='", "'>'", "'>='", 51 | "'<<'", "'>>'", "'+'", "'-'", "'&'", "'|'", "'&&'", "'||'", "'^'", "'!'", 52 | "'~'", "'?'", "':'", "';'", "','", "'='", "'=='", "'!='" 53 | }; 54 | } 55 | private static final String[] _LITERAL_NAMES = makeLiteralNames(); 56 | private static String[] makeSymbolicNames() { 57 | return new String[] { 58 | null, null, "Int", "If", "Else", "Return", "Struct", "LeftParen", "RightParen", 59 | "LeftBracket", "RightBracket", "LeftBrace", "RightBrace", "Less", "LessEqual", 60 | "Greater", "GreaterEqual", "LeftShift", "RightShift", "Plus", "Minus", 61 | "And", "Or", "AndAnd", "OrOr", "Caret", "Not", "Tilde", "Question", "Colon", 62 | "Semi", "Comma", "Assign", "Equal", "NotEqual", "Identifier", "DecimalInteger", 63 | "Whitespace", "Newline", "BlockComment", "LineComment" 64 | }; 65 | } 66 | private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames(); 67 | public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); 68 | 69 | /** 70 | * @deprecated Use {@link #VOCABULARY} instead. 71 | */ 72 | @Deprecated 73 | public static final String[] tokenNames; 74 | static { 75 | tokenNames = new String[_SYMBOLIC_NAMES.length]; 76 | for (int i = 0; i < tokenNames.length; i++) { 77 | tokenNames[i] = VOCABULARY.getLiteralName(i); 78 | if (tokenNames[i] == null) { 79 | tokenNames[i] = VOCABULARY.getSymbolicName(i); 80 | } 81 | 82 | if (tokenNames[i] == null) { 83 | tokenNames[i] = ""; 84 | } 85 | } 86 | } 87 | 88 | @Override 89 | @Deprecated 90 | public String[] getTokenNames() { 91 | return tokenNames; 92 | } 93 | 94 | @Override 95 | 96 | public Vocabulary getVocabulary() { 97 | return VOCABULARY; 98 | } 99 | 100 | 101 | public YxLexer(CharStream input) { 102 | super(input); 103 | _interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); 104 | } 105 | 106 | @Override 107 | public String getGrammarFileName() { return "Yx.g4"; } 108 | 109 | @Override 110 | public String[] getRuleNames() { return ruleNames; } 111 | 112 | @Override 113 | public String getSerializedATN() { return _serializedATN; } 114 | 115 | @Override 116 | public String[] getChannelNames() { return channelNames; } 117 | 118 | @Override 119 | public String[] getModeNames() { return modeNames; } 120 | 121 | @Override 122 | public ATN getATN() { return _ATN; } 123 | 124 | public static final String _serializedATN = 125 | "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2*\u00ee\b\1\4\2\t"+ 126 | "\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+ 127 | "\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+ 128 | "\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+ 129 | "\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36\t\36\4\37\t\37\4 \t \4!"+ 130 | "\t!\4\"\t\"\4#\t#\4$\t$\4%\t%\4&\t&\4\'\t\'\4(\t(\4)\t)\3\2\3\2\3\2\3"+ 131 | "\2\3\2\3\2\3\2\3\3\3\3\3\3\3\3\3\4\3\4\3\4\3\5\3\5\3\5\3\5\3\5\3\6\3\6"+ 132 | "\3\6\3\6\3\6\3\6\3\6\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\b\3\b\3\t\3\t\3\n\3"+ 133 | "\n\3\13\3\13\3\f\3\f\3\r\3\r\3\16\3\16\3\17\3\17\3\17\3\20\3\20\3\21\3"+ 134 | "\21\3\21\3\22\3\22\3\22\3\23\3\23\3\23\3\24\3\24\3\25\3\25\3\26\3\26\3"+ 135 | "\27\3\27\3\30\3\30\3\30\3\31\3\31\3\31\3\32\3\32\3\33\3\33\3\34\3\34\3"+ 136 | "\35\3\35\3\36\3\36\3\37\3\37\3 \3 \3!\3!\3\"\3\"\3\"\3#\3#\3#\3$\3$\7"+ 137 | "$\u00b7\n$\f$\16$\u00ba\13$\3%\3%\7%\u00be\n%\f%\16%\u00c1\13%\3%\5%\u00c4"+ 138 | "\n%\3&\6&\u00c7\n&\r&\16&\u00c8\3&\3&\3\'\3\'\5\'\u00cf\n\'\3\'\5\'\u00d2"+ 139 | "\n\'\3\'\3\'\3(\3(\3(\3(\7(\u00da\n(\f(\16(\u00dd\13(\3(\3(\3(\3(\3(\3"+ 140 | ")\3)\3)\3)\7)\u00e8\n)\f)\16)\u00eb\13)\3)\3)\3\u00db\2*\3\3\5\4\7\5\t"+ 141 | "\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35\20\37\21!\22#\23"+ 142 | "%\24\'\25)\26+\27-\30/\31\61\32\63\33\65\34\67\359\36;\37= ?!A\"C#E$G"+ 143 | "%I&K\'M(O)Q*\3\2\b\4\2C\\c|\6\2\62;C\\aac|\3\2\63;\3\2\62;\4\2\13\13\""+ 144 | "\"\4\2\f\f\17\17\2\u00f5\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2"+ 145 | "\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25"+ 146 | "\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2"+ 147 | "\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2"+ 148 | "\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2\2\2\2\67\3"+ 149 | "\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3\2\2\2\2C\3\2\2"+ 150 | "\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2\2\2\2O\3\2\2\2\2"+ 151 | "Q\3\2\2\2\3S\3\2\2\2\5Z\3\2\2\2\7^\3\2\2\2\ta\3\2\2\2\13f\3\2\2\2\rm\3"+ 152 | "\2\2\2\17t\3\2\2\2\21v\3\2\2\2\23x\3\2\2\2\25z\3\2\2\2\27|\3\2\2\2\31"+ 153 | "~\3\2\2\2\33\u0080\3\2\2\2\35\u0082\3\2\2\2\37\u0085\3\2\2\2!\u0087\3"+ 154 | "\2\2\2#\u008a\3\2\2\2%\u008d\3\2\2\2\'\u0090\3\2\2\2)\u0092\3\2\2\2+\u0094"+ 155 | "\3\2\2\2-\u0096\3\2\2\2/\u0098\3\2\2\2\61\u009b\3\2\2\2\63\u009e\3\2\2"+ 156 | "\2\65\u00a0\3\2\2\2\67\u00a2\3\2\2\29\u00a4\3\2\2\2;\u00a6\3\2\2\2=\u00a8"+ 157 | "\3\2\2\2?\u00aa\3\2\2\2A\u00ac\3\2\2\2C\u00ae\3\2\2\2E\u00b1\3\2\2\2G"+ 158 | "\u00b4\3\2\2\2I\u00c3\3\2\2\2K\u00c6\3\2\2\2M\u00d1\3\2\2\2O\u00d5\3\2"+ 159 | "\2\2Q\u00e3\3\2\2\2ST\7o\2\2TU\7c\2\2UV\7k\2\2VW\7p\2\2WX\7*\2\2XY\7+"+ 160 | "\2\2Y\4\3\2\2\2Z[\7k\2\2[\\\7p\2\2\\]\7v\2\2]\6\3\2\2\2^_\7k\2\2_`\7h"+ 161 | "\2\2`\b\3\2\2\2ab\7g\2\2bc\7n\2\2cd\7u\2\2de\7g\2\2e\n\3\2\2\2fg\7t\2"+ 162 | "\2gh\7g\2\2hi\7v\2\2ij\7w\2\2jk\7t\2\2kl\7p\2\2l\f\3\2\2\2mn\7u\2\2no"+ 163 | "\7v\2\2op\7t\2\2pq\7w\2\2qr\7e\2\2rs\7v\2\2s\16\3\2\2\2tu\7*\2\2u\20\3"+ 164 | "\2\2\2vw\7+\2\2w\22\3\2\2\2xy\7]\2\2y\24\3\2\2\2z{\7_\2\2{\26\3\2\2\2"+ 165 | "|}\7}\2\2}\30\3\2\2\2~\177\7\177\2\2\177\32\3\2\2\2\u0080\u0081\7>\2\2"+ 166 | "\u0081\34\3\2\2\2\u0082\u0083\7>\2\2\u0083\u0084\7?\2\2\u0084\36\3\2\2"+ 167 | "\2\u0085\u0086\7@\2\2\u0086 \3\2\2\2\u0087\u0088\7@\2\2\u0088\u0089\7"+ 168 | "?\2\2\u0089\"\3\2\2\2\u008a\u008b\7>\2\2\u008b\u008c\7>\2\2\u008c$\3\2"+ 169 | "\2\2\u008d\u008e\7@\2\2\u008e\u008f\7@\2\2\u008f&\3\2\2\2\u0090\u0091"+ 170 | "\7-\2\2\u0091(\3\2\2\2\u0092\u0093\7/\2\2\u0093*\3\2\2\2\u0094\u0095\7"+ 171 | "(\2\2\u0095,\3\2\2\2\u0096\u0097\7~\2\2\u0097.\3\2\2\2\u0098\u0099\7("+ 172 | "\2\2\u0099\u009a\7(\2\2\u009a\60\3\2\2\2\u009b\u009c\7~\2\2\u009c\u009d"+ 173 | "\7~\2\2\u009d\62\3\2\2\2\u009e\u009f\7`\2\2\u009f\64\3\2\2\2\u00a0\u00a1"+ 174 | "\7#\2\2\u00a1\66\3\2\2\2\u00a2\u00a3\7\u0080\2\2\u00a38\3\2\2\2\u00a4"+ 175 | "\u00a5\7A\2\2\u00a5:\3\2\2\2\u00a6\u00a7\7<\2\2\u00a7<\3\2\2\2\u00a8\u00a9"+ 176 | "\7=\2\2\u00a9>\3\2\2\2\u00aa\u00ab\7.\2\2\u00ab@\3\2\2\2\u00ac\u00ad\7"+ 177 | "?\2\2\u00adB\3\2\2\2\u00ae\u00af\7?\2\2\u00af\u00b0\7?\2\2\u00b0D\3\2"+ 178 | "\2\2\u00b1\u00b2\7#\2\2\u00b2\u00b3\7?\2\2\u00b3F\3\2\2\2\u00b4\u00b8"+ 179 | "\t\2\2\2\u00b5\u00b7\t\3\2\2\u00b6\u00b5\3\2\2\2\u00b7\u00ba\3\2\2\2\u00b8"+ 180 | "\u00b6\3\2\2\2\u00b8\u00b9\3\2\2\2\u00b9H\3\2\2\2\u00ba\u00b8\3\2\2\2"+ 181 | "\u00bb\u00bf\t\4\2\2\u00bc\u00be\t\5\2\2\u00bd\u00bc\3\2\2\2\u00be\u00c1"+ 182 | "\3\2\2\2\u00bf\u00bd\3\2\2\2\u00bf\u00c0\3\2\2\2\u00c0\u00c4\3\2\2\2\u00c1"+ 183 | "\u00bf\3\2\2\2\u00c2\u00c4\7\62\2\2\u00c3\u00bb\3\2\2\2\u00c3\u00c2\3"+ 184 | "\2\2\2\u00c4J\3\2\2\2\u00c5\u00c7\t\6\2\2\u00c6\u00c5\3\2\2\2\u00c7\u00c8"+ 185 | "\3\2\2\2\u00c8\u00c6\3\2\2\2\u00c8\u00c9\3\2\2\2\u00c9\u00ca\3\2\2\2\u00ca"+ 186 | "\u00cb\b&\2\2\u00cbL\3\2\2\2\u00cc\u00ce\7\17\2\2\u00cd\u00cf\7\f\2\2"+ 187 | "\u00ce\u00cd\3\2\2\2\u00ce\u00cf\3\2\2\2\u00cf\u00d2\3\2\2\2\u00d0\u00d2"+ 188 | "\7\f\2\2\u00d1\u00cc\3\2\2\2\u00d1\u00d0\3\2\2\2\u00d2\u00d3\3\2\2\2\u00d3"+ 189 | "\u00d4\b\'\2\2\u00d4N\3\2\2\2\u00d5\u00d6\7\61\2\2\u00d6\u00d7\7,\2\2"+ 190 | "\u00d7\u00db\3\2\2\2\u00d8\u00da\13\2\2\2\u00d9\u00d8\3\2\2\2\u00da\u00dd"+ 191 | "\3\2\2\2\u00db\u00dc\3\2\2\2\u00db\u00d9\3\2\2\2\u00dc\u00de\3\2\2\2\u00dd"+ 192 | "\u00db\3\2\2\2\u00de\u00df\7,\2\2\u00df\u00e0\7\61\2\2\u00e0\u00e1\3\2"+ 193 | "\2\2\u00e1\u00e2\b(\2\2\u00e2P\3\2\2\2\u00e3\u00e4\7\61\2\2\u00e4\u00e5"+ 194 | "\7\61\2\2\u00e5\u00e9\3\2\2\2\u00e6\u00e8\n\7\2\2\u00e7\u00e6\3\2\2\2"+ 195 | "\u00e8\u00eb\3\2\2\2\u00e9\u00e7\3\2\2\2\u00e9\u00ea\3\2\2\2\u00ea\u00ec"+ 196 | "\3\2\2\2\u00eb\u00e9\3\2\2\2\u00ec\u00ed\b)\2\2\u00edR\3\2\2\2\13\2\u00b8"+ 197 | "\u00bf\u00c3\u00c8\u00ce\u00d1\u00db\u00e9\3\b\2\2"; 198 | public static final ATN _ATN = 199 | new ATNDeserializer().deserialize(_serializedATN.toCharArray()); 200 | static { 201 | _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; 202 | for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) { 203 | _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); 204 | } 205 | } 206 | } -------------------------------------------------------------------------------- /src/Parser/YxLexer.tokens: -------------------------------------------------------------------------------- 1 | T__0=1 2 | Int=2 3 | If=3 4 | Else=4 5 | Return=5 6 | Struct=6 7 | LeftParen=7 8 | RightParen=8 9 | LeftBracket=9 10 | RightBracket=10 11 | LeftBrace=11 12 | RightBrace=12 13 | Less=13 14 | LessEqual=14 15 | Greater=15 16 | GreaterEqual=16 17 | LeftShift=17 18 | RightShift=18 19 | Plus=19 20 | Minus=20 21 | And=21 22 | Or=22 23 | AndAnd=23 24 | OrOr=24 25 | Caret=25 26 | Not=26 27 | Tilde=27 28 | Question=28 29 | Colon=29 30 | Semi=30 31 | Comma=31 32 | Assign=32 33 | Equal=33 34 | NotEqual=34 35 | Identifier=35 36 | DecimalInteger=36 37 | Whitespace=37 38 | Newline=38 39 | BlockComment=39 40 | LineComment=40 41 | 'main()'=1 42 | 'int'=2 43 | 'if'=3 44 | 'else'=4 45 | 'return'=5 46 | 'struct'=6 47 | '('=7 48 | ')'=8 49 | '['=9 50 | ']'=10 51 | '{'=11 52 | '}'=12 53 | '<'=13 54 | '<='=14 55 | '>'=15 56 | '>='=16 57 | '<<'=17 58 | '>>'=18 59 | '+'=19 60 | '-'=20 61 | '&'=21 62 | '|'=22 63 | '&&'=23 64 | '||'=24 65 | '^'=25 66 | '!'=26 67 | '~'=27 68 | '?'=28 69 | ':'=29 70 | ';'=30 71 | ','=31 72 | '='=32 73 | '=='=33 74 | '!='=34 75 | -------------------------------------------------------------------------------- /src/Parser/YxListener.java: -------------------------------------------------------------------------------- 1 | // Generated from Yx.g4 by ANTLR 4.7.2 2 | package Parser; 3 | import org.antlr.v4.runtime.tree.ParseTreeListener; 4 | 5 | /** 6 | * This interface defines a complete listener for a parse tree produced by 7 | * {@link YxParser}. 8 | */ 9 | public interface YxListener extends ParseTreeListener { 10 | /** 11 | * Enter a parse tree produced by {@link YxParser#program}. 12 | * @param ctx the parse tree 13 | */ 14 | void enterProgram(YxParser.ProgramContext ctx); 15 | /** 16 | * Exit a parse tree produced by {@link YxParser#program}. 17 | * @param ctx the parse tree 18 | */ 19 | void exitProgram(YxParser.ProgramContext ctx); 20 | /** 21 | * Enter a parse tree produced by {@link YxParser#mainFn}. 22 | * @param ctx the parse tree 23 | */ 24 | void enterMainFn(YxParser.MainFnContext ctx); 25 | /** 26 | * Exit a parse tree produced by {@link YxParser#mainFn}. 27 | * @param ctx the parse tree 28 | */ 29 | void exitMainFn(YxParser.MainFnContext ctx); 30 | /** 31 | * Enter a parse tree produced by {@link YxParser#varDef}. 32 | * @param ctx the parse tree 33 | */ 34 | void enterVarDef(YxParser.VarDefContext ctx); 35 | /** 36 | * Exit a parse tree produced by {@link YxParser#varDef}. 37 | * @param ctx the parse tree 38 | */ 39 | void exitVarDef(YxParser.VarDefContext ctx); 40 | /** 41 | * Enter a parse tree produced by {@link YxParser#classDef}. 42 | * @param ctx the parse tree 43 | */ 44 | void enterClassDef(YxParser.ClassDefContext ctx); 45 | /** 46 | * Exit a parse tree produced by {@link YxParser#classDef}. 47 | * @param ctx the parse tree 48 | */ 49 | void exitClassDef(YxParser.ClassDefContext ctx); 50 | /** 51 | * Enter a parse tree produced by {@link YxParser#suite}. 52 | * @param ctx the parse tree 53 | */ 54 | void enterSuite(YxParser.SuiteContext ctx); 55 | /** 56 | * Exit a parse tree produced by {@link YxParser#suite}. 57 | * @param ctx the parse tree 58 | */ 59 | void exitSuite(YxParser.SuiteContext ctx); 60 | /** 61 | * Enter a parse tree produced by the {@code block} 62 | * labeled alternative in {@link YxParser#statement}. 63 | * @param ctx the parse tree 64 | */ 65 | void enterBlock(YxParser.BlockContext ctx); 66 | /** 67 | * Exit a parse tree produced by the {@code block} 68 | * labeled alternative in {@link YxParser#statement}. 69 | * @param ctx the parse tree 70 | */ 71 | void exitBlock(YxParser.BlockContext ctx); 72 | /** 73 | * Enter a parse tree produced by the {@code vardefStmt} 74 | * labeled alternative in {@link YxParser#statement}. 75 | * @param ctx the parse tree 76 | */ 77 | void enterVardefStmt(YxParser.VardefStmtContext ctx); 78 | /** 79 | * Exit a parse tree produced by the {@code vardefStmt} 80 | * labeled alternative in {@link YxParser#statement}. 81 | * @param ctx the parse tree 82 | */ 83 | void exitVardefStmt(YxParser.VardefStmtContext ctx); 84 | /** 85 | * Enter a parse tree produced by the {@code ifStmt} 86 | * labeled alternative in {@link YxParser#statement}. 87 | * @param ctx the parse tree 88 | */ 89 | void enterIfStmt(YxParser.IfStmtContext ctx); 90 | /** 91 | * Exit a parse tree produced by the {@code ifStmt} 92 | * labeled alternative in {@link YxParser#statement}. 93 | * @param ctx the parse tree 94 | */ 95 | void exitIfStmt(YxParser.IfStmtContext ctx); 96 | /** 97 | * Enter a parse tree produced by the {@code returnStmt} 98 | * labeled alternative in {@link YxParser#statement}. 99 | * @param ctx the parse tree 100 | */ 101 | void enterReturnStmt(YxParser.ReturnStmtContext ctx); 102 | /** 103 | * Exit a parse tree produced by the {@code returnStmt} 104 | * labeled alternative in {@link YxParser#statement}. 105 | * @param ctx the parse tree 106 | */ 107 | void exitReturnStmt(YxParser.ReturnStmtContext ctx); 108 | /** 109 | * Enter a parse tree produced by the {@code pureExprStmt} 110 | * labeled alternative in {@link YxParser#statement}. 111 | * @param ctx the parse tree 112 | */ 113 | void enterPureExprStmt(YxParser.PureExprStmtContext ctx); 114 | /** 115 | * Exit a parse tree produced by the {@code pureExprStmt} 116 | * labeled alternative in {@link YxParser#statement}. 117 | * @param ctx the parse tree 118 | */ 119 | void exitPureExprStmt(YxParser.PureExprStmtContext ctx); 120 | /** 121 | * Enter a parse tree produced by the {@code emptyStmt} 122 | * labeled alternative in {@link YxParser#statement}. 123 | * @param ctx the parse tree 124 | */ 125 | void enterEmptyStmt(YxParser.EmptyStmtContext ctx); 126 | /** 127 | * Exit a parse tree produced by the {@code emptyStmt} 128 | * labeled alternative in {@link YxParser#statement}. 129 | * @param ctx the parse tree 130 | */ 131 | void exitEmptyStmt(YxParser.EmptyStmtContext ctx); 132 | /** 133 | * Enter a parse tree produced by the {@code atomExpr} 134 | * labeled alternative in {@link YxParser#expression}. 135 | * @param ctx the parse tree 136 | */ 137 | void enterAtomExpr(YxParser.AtomExprContext ctx); 138 | /** 139 | * Exit a parse tree produced by the {@code atomExpr} 140 | * labeled alternative in {@link YxParser#expression}. 141 | * @param ctx the parse tree 142 | */ 143 | void exitAtomExpr(YxParser.AtomExprContext ctx); 144 | /** 145 | * Enter a parse tree produced by the {@code binaryExpr} 146 | * labeled alternative in {@link YxParser#expression}. 147 | * @param ctx the parse tree 148 | */ 149 | void enterBinaryExpr(YxParser.BinaryExprContext ctx); 150 | /** 151 | * Exit a parse tree produced by the {@code binaryExpr} 152 | * labeled alternative in {@link YxParser#expression}. 153 | * @param ctx the parse tree 154 | */ 155 | void exitBinaryExpr(YxParser.BinaryExprContext ctx); 156 | /** 157 | * Enter a parse tree produced by the {@code assignExpr} 158 | * labeled alternative in {@link YxParser#expression}. 159 | * @param ctx the parse tree 160 | */ 161 | void enterAssignExpr(YxParser.AssignExprContext ctx); 162 | /** 163 | * Exit a parse tree produced by the {@code assignExpr} 164 | * labeled alternative in {@link YxParser#expression}. 165 | * @param ctx the parse tree 166 | */ 167 | void exitAssignExpr(YxParser.AssignExprContext ctx); 168 | /** 169 | * Enter a parse tree produced by {@link YxParser#primary}. 170 | * @param ctx the parse tree 171 | */ 172 | void enterPrimary(YxParser.PrimaryContext ctx); 173 | /** 174 | * Exit a parse tree produced by {@link YxParser#primary}. 175 | * @param ctx the parse tree 176 | */ 177 | void exitPrimary(YxParser.PrimaryContext ctx); 178 | /** 179 | * Enter a parse tree produced by {@link YxParser#literal}. 180 | * @param ctx the parse tree 181 | */ 182 | void enterLiteral(YxParser.LiteralContext ctx); 183 | /** 184 | * Exit a parse tree produced by {@link YxParser#literal}. 185 | * @param ctx the parse tree 186 | */ 187 | void exitLiteral(YxParser.LiteralContext ctx); 188 | /** 189 | * Enter a parse tree produced by {@link YxParser#type}. 190 | * @param ctx the parse tree 191 | */ 192 | void enterType(YxParser.TypeContext ctx); 193 | /** 194 | * Exit a parse tree produced by {@link YxParser#type}. 195 | * @param ctx the parse tree 196 | */ 197 | void exitType(YxParser.TypeContext ctx); 198 | } -------------------------------------------------------------------------------- /src/Parser/YxParser.java: -------------------------------------------------------------------------------- 1 | // Generated from Yx.g4 by ANTLR 4.7.2 2 | package Parser; 3 | 4 | import org.antlr.v4.runtime.atn.*; 5 | import org.antlr.v4.runtime.dfa.DFA; 6 | import org.antlr.v4.runtime.*; 7 | import org.antlr.v4.runtime.misc.*; 8 | import org.antlr.v4.runtime.tree.*; 9 | import java.util.List; 10 | import java.util.Iterator; 11 | import java.util.ArrayList; 12 | 13 | @SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) 14 | public class YxParser extends Parser { 15 | static { RuntimeMetaData.checkVersion("4.7.2", RuntimeMetaData.VERSION); } 16 | 17 | protected static final DFA[] _decisionToDFA; 18 | protected static final PredictionContextCache _sharedContextCache = 19 | new PredictionContextCache(); 20 | public static final int 21 | T__0=1, Int=2, If=3, Else=4, Return=5, Struct=6, LeftParen=7, RightParen=8, 22 | LeftBracket=9, RightBracket=10, LeftBrace=11, RightBrace=12, Less=13, 23 | LessEqual=14, Greater=15, GreaterEqual=16, LeftShift=17, RightShift=18, 24 | Plus=19, Minus=20, And=21, Or=22, AndAnd=23, OrOr=24, Caret=25, Not=26, 25 | Tilde=27, Question=28, Colon=29, Semi=30, Comma=31, Assign=32, Equal=33, 26 | NotEqual=34, Identifier=35, DecimalInteger=36, Whitespace=37, Newline=38, 27 | BlockComment=39, LineComment=40; 28 | public static final int 29 | RULE_program = 0, RULE_mainFn = 1, RULE_varDef = 2, RULE_classDef = 3, 30 | RULE_suite = 4, RULE_statement = 5, RULE_expression = 6, RULE_primary = 7, 31 | RULE_literal = 8, RULE_type = 9; 32 | private static String[] makeRuleNames() { 33 | return new String[] { 34 | "program", "mainFn", "varDef", "classDef", "suite", "statement", "expression", 35 | "primary", "literal", "type" 36 | }; 37 | } 38 | public static final String[] ruleNames = makeRuleNames(); 39 | 40 | private static String[] makeLiteralNames() { 41 | return new String[] { 42 | null, "'main()'", "'int'", "'if'", "'else'", "'return'", "'struct'", 43 | "'('", "')'", "'['", "']'", "'{'", "'}'", "'<'", "'<='", "'>'", "'>='", 44 | "'<<'", "'>>'", "'+'", "'-'", "'&'", "'|'", "'&&'", "'||'", "'^'", "'!'", 45 | "'~'", "'?'", "':'", "';'", "','", "'='", "'=='", "'!='" 46 | }; 47 | } 48 | private static final String[] _LITERAL_NAMES = makeLiteralNames(); 49 | private static String[] makeSymbolicNames() { 50 | return new String[] { 51 | null, null, "Int", "If", "Else", "Return", "Struct", "LeftParen", "RightParen", 52 | "LeftBracket", "RightBracket", "LeftBrace", "RightBrace", "Less", "LessEqual", 53 | "Greater", "GreaterEqual", "LeftShift", "RightShift", "Plus", "Minus", 54 | "And", "Or", "AndAnd", "OrOr", "Caret", "Not", "Tilde", "Question", "Colon", 55 | "Semi", "Comma", "Assign", "Equal", "NotEqual", "Identifier", "DecimalInteger", 56 | "Whitespace", "Newline", "BlockComment", "LineComment" 57 | }; 58 | } 59 | private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames(); 60 | public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); 61 | 62 | /** 63 | * @deprecated Use {@link #VOCABULARY} instead. 64 | */ 65 | @Deprecated 66 | public static final String[] tokenNames; 67 | static { 68 | tokenNames = new String[_SYMBOLIC_NAMES.length]; 69 | for (int i = 0; i < tokenNames.length; i++) { 70 | tokenNames[i] = VOCABULARY.getLiteralName(i); 71 | if (tokenNames[i] == null) { 72 | tokenNames[i] = VOCABULARY.getSymbolicName(i); 73 | } 74 | 75 | if (tokenNames[i] == null) { 76 | tokenNames[i] = ""; 77 | } 78 | } 79 | } 80 | 81 | @Override 82 | @Deprecated 83 | public String[] getTokenNames() { 84 | return tokenNames; 85 | } 86 | 87 | @Override 88 | 89 | public Vocabulary getVocabulary() { 90 | return VOCABULARY; 91 | } 92 | 93 | @Override 94 | public String getGrammarFileName() { return "Yx.g4"; } 95 | 96 | @Override 97 | public String[] getRuleNames() { return ruleNames; } 98 | 99 | @Override 100 | public String getSerializedATN() { return _serializedATN; } 101 | 102 | @Override 103 | public ATN getATN() { return _ATN; } 104 | 105 | public YxParser(TokenStream input) { 106 | super(input); 107 | _interp = new ParserATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); 108 | } 109 | 110 | public static class ProgramContext extends ParserRuleContext { 111 | public MainFnContext mainFn() { 112 | return getRuleContext(MainFnContext.class,0); 113 | } 114 | public List classDef() { 115 | return getRuleContexts(ClassDefContext.class); 116 | } 117 | public ClassDefContext classDef(int i) { 118 | return getRuleContext(ClassDefContext.class,i); 119 | } 120 | public ProgramContext(ParserRuleContext parent, int invokingState) { 121 | super(parent, invokingState); 122 | } 123 | @Override public int getRuleIndex() { return RULE_program; } 124 | @Override 125 | public void enterRule(ParseTreeListener listener) { 126 | if ( listener instanceof YxListener ) ((YxListener)listener).enterProgram(this); 127 | } 128 | @Override 129 | public void exitRule(ParseTreeListener listener) { 130 | if ( listener instanceof YxListener ) ((YxListener)listener).exitProgram(this); 131 | } 132 | @Override 133 | public T accept(ParseTreeVisitor visitor) { 134 | if ( visitor instanceof YxVisitor ) return ((YxVisitor)visitor).visitProgram(this); 135 | else return visitor.visitChildren(this); 136 | } 137 | } 138 | 139 | public final ProgramContext program() throws RecognitionException { 140 | ProgramContext _localctx = new ProgramContext(_ctx, getState()); 141 | enterRule(_localctx, 0, RULE_program); 142 | int _la; 143 | try { 144 | enterOuterAlt(_localctx, 1); 145 | { 146 | setState(23); 147 | _errHandler.sync(this); 148 | _la = _input.LA(1); 149 | while (_la==Struct) { 150 | { 151 | { 152 | setState(20); 153 | classDef(); 154 | } 155 | } 156 | setState(25); 157 | _errHandler.sync(this); 158 | _la = _input.LA(1); 159 | } 160 | setState(26); 161 | mainFn(); 162 | } 163 | } 164 | catch (RecognitionException re) { 165 | _localctx.exception = re; 166 | _errHandler.reportError(this, re); 167 | _errHandler.recover(this, re); 168 | } 169 | finally { 170 | exitRule(); 171 | } 172 | return _localctx; 173 | } 174 | 175 | public static class MainFnContext extends ParserRuleContext { 176 | public TerminalNode Int() { return getToken(YxParser.Int, 0); } 177 | public SuiteContext suite() { 178 | return getRuleContext(SuiteContext.class,0); 179 | } 180 | public TerminalNode EOF() { return getToken(YxParser.EOF, 0); } 181 | public MainFnContext(ParserRuleContext parent, int invokingState) { 182 | super(parent, invokingState); 183 | } 184 | @Override public int getRuleIndex() { return RULE_mainFn; } 185 | @Override 186 | public void enterRule(ParseTreeListener listener) { 187 | if ( listener instanceof YxListener ) ((YxListener)listener).enterMainFn(this); 188 | } 189 | @Override 190 | public void exitRule(ParseTreeListener listener) { 191 | if ( listener instanceof YxListener ) ((YxListener)listener).exitMainFn(this); 192 | } 193 | @Override 194 | public T accept(ParseTreeVisitor visitor) { 195 | if ( visitor instanceof YxVisitor ) return ((YxVisitor)visitor).visitMainFn(this); 196 | else return visitor.visitChildren(this); 197 | } 198 | } 199 | 200 | public final MainFnContext mainFn() throws RecognitionException { 201 | MainFnContext _localctx = new MainFnContext(_ctx, getState()); 202 | enterRule(_localctx, 2, RULE_mainFn); 203 | try { 204 | enterOuterAlt(_localctx, 1); 205 | { 206 | setState(28); 207 | match(Int); 208 | setState(29); 209 | match(T__0); 210 | setState(30); 211 | suite(); 212 | setState(31); 213 | match(EOF); 214 | } 215 | } 216 | catch (RecognitionException re) { 217 | _localctx.exception = re; 218 | _errHandler.reportError(this, re); 219 | _errHandler.recover(this, re); 220 | } 221 | finally { 222 | exitRule(); 223 | } 224 | return _localctx; 225 | } 226 | 227 | public static class VarDefContext extends ParserRuleContext { 228 | public TypeContext type() { 229 | return getRuleContext(TypeContext.class,0); 230 | } 231 | public TerminalNode Identifier() { return getToken(YxParser.Identifier, 0); } 232 | public TerminalNode Semi() { return getToken(YxParser.Semi, 0); } 233 | public TerminalNode Assign() { return getToken(YxParser.Assign, 0); } 234 | public ExpressionContext expression() { 235 | return getRuleContext(ExpressionContext.class,0); 236 | } 237 | public VarDefContext(ParserRuleContext parent, int invokingState) { 238 | super(parent, invokingState); 239 | } 240 | @Override public int getRuleIndex() { return RULE_varDef; } 241 | @Override 242 | public void enterRule(ParseTreeListener listener) { 243 | if ( listener instanceof YxListener ) ((YxListener)listener).enterVarDef(this); 244 | } 245 | @Override 246 | public void exitRule(ParseTreeListener listener) { 247 | if ( listener instanceof YxListener ) ((YxListener)listener).exitVarDef(this); 248 | } 249 | @Override 250 | public T accept(ParseTreeVisitor visitor) { 251 | if ( visitor instanceof YxVisitor ) return ((YxVisitor)visitor).visitVarDef(this); 252 | else return visitor.visitChildren(this); 253 | } 254 | } 255 | 256 | public final VarDefContext varDef() throws RecognitionException { 257 | VarDefContext _localctx = new VarDefContext(_ctx, getState()); 258 | enterRule(_localctx, 4, RULE_varDef); 259 | int _la; 260 | try { 261 | enterOuterAlt(_localctx, 1); 262 | { 263 | setState(33); 264 | type(); 265 | setState(34); 266 | match(Identifier); 267 | setState(37); 268 | _errHandler.sync(this); 269 | _la = _input.LA(1); 270 | if (_la==Assign) { 271 | { 272 | setState(35); 273 | match(Assign); 274 | setState(36); 275 | expression(0); 276 | } 277 | } 278 | 279 | setState(39); 280 | match(Semi); 281 | } 282 | } 283 | catch (RecognitionException re) { 284 | _localctx.exception = re; 285 | _errHandler.reportError(this, re); 286 | _errHandler.recover(this, re); 287 | } 288 | finally { 289 | exitRule(); 290 | } 291 | return _localctx; 292 | } 293 | 294 | public static class ClassDefContext extends ParserRuleContext { 295 | public TerminalNode Struct() { return getToken(YxParser.Struct, 0); } 296 | public TerminalNode Identifier() { return getToken(YxParser.Identifier, 0); } 297 | public TerminalNode LeftBrace() { return getToken(YxParser.LeftBrace, 0); } 298 | public TerminalNode RightBrace() { return getToken(YxParser.RightBrace, 0); } 299 | public TerminalNode Semi() { return getToken(YxParser.Semi, 0); } 300 | public List varDef() { 301 | return getRuleContexts(VarDefContext.class); 302 | } 303 | public VarDefContext varDef(int i) { 304 | return getRuleContext(VarDefContext.class,i); 305 | } 306 | public ClassDefContext(ParserRuleContext parent, int invokingState) { 307 | super(parent, invokingState); 308 | } 309 | @Override public int getRuleIndex() { return RULE_classDef; } 310 | @Override 311 | public void enterRule(ParseTreeListener listener) { 312 | if ( listener instanceof YxListener ) ((YxListener)listener).enterClassDef(this); 313 | } 314 | @Override 315 | public void exitRule(ParseTreeListener listener) { 316 | if ( listener instanceof YxListener ) ((YxListener)listener).exitClassDef(this); 317 | } 318 | @Override 319 | public T accept(ParseTreeVisitor visitor) { 320 | if ( visitor instanceof YxVisitor ) return ((YxVisitor)visitor).visitClassDef(this); 321 | else return visitor.visitChildren(this); 322 | } 323 | } 324 | 325 | public final ClassDefContext classDef() throws RecognitionException { 326 | ClassDefContext _localctx = new ClassDefContext(_ctx, getState()); 327 | enterRule(_localctx, 6, RULE_classDef); 328 | int _la; 329 | try { 330 | enterOuterAlt(_localctx, 1); 331 | { 332 | setState(41); 333 | match(Struct); 334 | setState(42); 335 | match(Identifier); 336 | setState(43); 337 | match(LeftBrace); 338 | setState(47); 339 | _errHandler.sync(this); 340 | _la = _input.LA(1); 341 | while (_la==Int || _la==Identifier) { 342 | { 343 | { 344 | setState(44); 345 | varDef(); 346 | } 347 | } 348 | setState(49); 349 | _errHandler.sync(this); 350 | _la = _input.LA(1); 351 | } 352 | setState(50); 353 | match(RightBrace); 354 | setState(51); 355 | match(Semi); 356 | } 357 | } 358 | catch (RecognitionException re) { 359 | _localctx.exception = re; 360 | _errHandler.reportError(this, re); 361 | _errHandler.recover(this, re); 362 | } 363 | finally { 364 | exitRule(); 365 | } 366 | return _localctx; 367 | } 368 | 369 | public static class SuiteContext extends ParserRuleContext { 370 | public TerminalNode LeftBrace() { return getToken(YxParser.LeftBrace, 0); } 371 | public TerminalNode RightBrace() { return getToken(YxParser.RightBrace, 0); } 372 | public List statement() { 373 | return getRuleContexts(StatementContext.class); 374 | } 375 | public StatementContext statement(int i) { 376 | return getRuleContext(StatementContext.class,i); 377 | } 378 | public SuiteContext(ParserRuleContext parent, int invokingState) { 379 | super(parent, invokingState); 380 | } 381 | @Override public int getRuleIndex() { return RULE_suite; } 382 | @Override 383 | public void enterRule(ParseTreeListener listener) { 384 | if ( listener instanceof YxListener ) ((YxListener)listener).enterSuite(this); 385 | } 386 | @Override 387 | public void exitRule(ParseTreeListener listener) { 388 | if ( listener instanceof YxListener ) ((YxListener)listener).exitSuite(this); 389 | } 390 | @Override 391 | public T accept(ParseTreeVisitor visitor) { 392 | if ( visitor instanceof YxVisitor ) return ((YxVisitor)visitor).visitSuite(this); 393 | else return visitor.visitChildren(this); 394 | } 395 | } 396 | 397 | public final SuiteContext suite() throws RecognitionException { 398 | SuiteContext _localctx = new SuiteContext(_ctx, getState()); 399 | enterRule(_localctx, 8, RULE_suite); 400 | int _la; 401 | try { 402 | enterOuterAlt(_localctx, 1); 403 | { 404 | setState(53); 405 | match(LeftBrace); 406 | setState(57); 407 | _errHandler.sync(this); 408 | _la = _input.LA(1); 409 | while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << Int) | (1L << If) | (1L << Return) | (1L << LeftParen) | (1L << LeftBrace) | (1L << Semi) | (1L << Identifier) | (1L << DecimalInteger))) != 0)) { 410 | { 411 | { 412 | setState(54); 413 | statement(); 414 | } 415 | } 416 | setState(59); 417 | _errHandler.sync(this); 418 | _la = _input.LA(1); 419 | } 420 | setState(60); 421 | match(RightBrace); 422 | } 423 | } 424 | catch (RecognitionException re) { 425 | _localctx.exception = re; 426 | _errHandler.reportError(this, re); 427 | _errHandler.recover(this, re); 428 | } 429 | finally { 430 | exitRule(); 431 | } 432 | return _localctx; 433 | } 434 | 435 | public static class StatementContext extends ParserRuleContext { 436 | public StatementContext(ParserRuleContext parent, int invokingState) { 437 | super(parent, invokingState); 438 | } 439 | @Override public int getRuleIndex() { return RULE_statement; } 440 | 441 | public StatementContext() { } 442 | public void copyFrom(StatementContext ctx) { 443 | super.copyFrom(ctx); 444 | } 445 | } 446 | public static class IfStmtContext extends StatementContext { 447 | public StatementContext trueStmt; 448 | public StatementContext falseStmt; 449 | public TerminalNode If() { return getToken(YxParser.If, 0); } 450 | public TerminalNode LeftParen() { return getToken(YxParser.LeftParen, 0); } 451 | public ExpressionContext expression() { 452 | return getRuleContext(ExpressionContext.class,0); 453 | } 454 | public TerminalNode RightParen() { return getToken(YxParser.RightParen, 0); } 455 | public List statement() { 456 | return getRuleContexts(StatementContext.class); 457 | } 458 | public StatementContext statement(int i) { 459 | return getRuleContext(StatementContext.class,i); 460 | } 461 | public TerminalNode Else() { return getToken(YxParser.Else, 0); } 462 | public IfStmtContext(StatementContext ctx) { copyFrom(ctx); } 463 | @Override 464 | public void enterRule(ParseTreeListener listener) { 465 | if ( listener instanceof YxListener ) ((YxListener)listener).enterIfStmt(this); 466 | } 467 | @Override 468 | public void exitRule(ParseTreeListener listener) { 469 | if ( listener instanceof YxListener ) ((YxListener)listener).exitIfStmt(this); 470 | } 471 | @Override 472 | public T accept(ParseTreeVisitor visitor) { 473 | if ( visitor instanceof YxVisitor ) return ((YxVisitor)visitor).visitIfStmt(this); 474 | else return visitor.visitChildren(this); 475 | } 476 | } 477 | public static class EmptyStmtContext extends StatementContext { 478 | public TerminalNode Semi() { return getToken(YxParser.Semi, 0); } 479 | public EmptyStmtContext(StatementContext ctx) { copyFrom(ctx); } 480 | @Override 481 | public void enterRule(ParseTreeListener listener) { 482 | if ( listener instanceof YxListener ) ((YxListener)listener).enterEmptyStmt(this); 483 | } 484 | @Override 485 | public void exitRule(ParseTreeListener listener) { 486 | if ( listener instanceof YxListener ) ((YxListener)listener).exitEmptyStmt(this); 487 | } 488 | @Override 489 | public T accept(ParseTreeVisitor visitor) { 490 | if ( visitor instanceof YxVisitor ) return ((YxVisitor)visitor).visitEmptyStmt(this); 491 | else return visitor.visitChildren(this); 492 | } 493 | } 494 | public static class BlockContext extends StatementContext { 495 | public SuiteContext suite() { 496 | return getRuleContext(SuiteContext.class,0); 497 | } 498 | public BlockContext(StatementContext ctx) { copyFrom(ctx); } 499 | @Override 500 | public void enterRule(ParseTreeListener listener) { 501 | if ( listener instanceof YxListener ) ((YxListener)listener).enterBlock(this); 502 | } 503 | @Override 504 | public void exitRule(ParseTreeListener listener) { 505 | if ( listener instanceof YxListener ) ((YxListener)listener).exitBlock(this); 506 | } 507 | @Override 508 | public T accept(ParseTreeVisitor visitor) { 509 | if ( visitor instanceof YxVisitor ) return ((YxVisitor)visitor).visitBlock(this); 510 | else return visitor.visitChildren(this); 511 | } 512 | } 513 | public static class ReturnStmtContext extends StatementContext { 514 | public TerminalNode Return() { return getToken(YxParser.Return, 0); } 515 | public TerminalNode Semi() { return getToken(YxParser.Semi, 0); } 516 | public ExpressionContext expression() { 517 | return getRuleContext(ExpressionContext.class,0); 518 | } 519 | public ReturnStmtContext(StatementContext ctx) { copyFrom(ctx); } 520 | @Override 521 | public void enterRule(ParseTreeListener listener) { 522 | if ( listener instanceof YxListener ) ((YxListener)listener).enterReturnStmt(this); 523 | } 524 | @Override 525 | public void exitRule(ParseTreeListener listener) { 526 | if ( listener instanceof YxListener ) ((YxListener)listener).exitReturnStmt(this); 527 | } 528 | @Override 529 | public T accept(ParseTreeVisitor visitor) { 530 | if ( visitor instanceof YxVisitor ) return ((YxVisitor)visitor).visitReturnStmt(this); 531 | else return visitor.visitChildren(this); 532 | } 533 | } 534 | public static class VardefStmtContext extends StatementContext { 535 | public VarDefContext varDef() { 536 | return getRuleContext(VarDefContext.class,0); 537 | } 538 | public VardefStmtContext(StatementContext ctx) { copyFrom(ctx); } 539 | @Override 540 | public void enterRule(ParseTreeListener listener) { 541 | if ( listener instanceof YxListener ) ((YxListener)listener).enterVardefStmt(this); 542 | } 543 | @Override 544 | public void exitRule(ParseTreeListener listener) { 545 | if ( listener instanceof YxListener ) ((YxListener)listener).exitVardefStmt(this); 546 | } 547 | @Override 548 | public T accept(ParseTreeVisitor visitor) { 549 | if ( visitor instanceof YxVisitor ) return ((YxVisitor)visitor).visitVardefStmt(this); 550 | else return visitor.visitChildren(this); 551 | } 552 | } 553 | public static class PureExprStmtContext extends StatementContext { 554 | public ExpressionContext expression() { 555 | return getRuleContext(ExpressionContext.class,0); 556 | } 557 | public TerminalNode Semi() { return getToken(YxParser.Semi, 0); } 558 | public PureExprStmtContext(StatementContext ctx) { copyFrom(ctx); } 559 | @Override 560 | public void enterRule(ParseTreeListener listener) { 561 | if ( listener instanceof YxListener ) ((YxListener)listener).enterPureExprStmt(this); 562 | } 563 | @Override 564 | public void exitRule(ParseTreeListener listener) { 565 | if ( listener instanceof YxListener ) ((YxListener)listener).exitPureExprStmt(this); 566 | } 567 | @Override 568 | public T accept(ParseTreeVisitor visitor) { 569 | if ( visitor instanceof YxVisitor ) return ((YxVisitor)visitor).visitPureExprStmt(this); 570 | else return visitor.visitChildren(this); 571 | } 572 | } 573 | 574 | public final StatementContext statement() throws RecognitionException { 575 | StatementContext _localctx = new StatementContext(_ctx, getState()); 576 | enterRule(_localctx, 10, RULE_statement); 577 | int _la; 578 | try { 579 | setState(82); 580 | _errHandler.sync(this); 581 | switch ( getInterpreter().adaptivePredict(_input,6,_ctx) ) { 582 | case 1: 583 | _localctx = new BlockContext(_localctx); 584 | enterOuterAlt(_localctx, 1); 585 | { 586 | setState(62); 587 | suite(); 588 | } 589 | break; 590 | case 2: 591 | _localctx = new VardefStmtContext(_localctx); 592 | enterOuterAlt(_localctx, 2); 593 | { 594 | setState(63); 595 | varDef(); 596 | } 597 | break; 598 | case 3: 599 | _localctx = new IfStmtContext(_localctx); 600 | enterOuterAlt(_localctx, 3); 601 | { 602 | setState(64); 603 | match(If); 604 | setState(65); 605 | match(LeftParen); 606 | setState(66); 607 | expression(0); 608 | setState(67); 609 | match(RightParen); 610 | setState(68); 611 | ((IfStmtContext)_localctx).trueStmt = statement(); 612 | setState(71); 613 | _errHandler.sync(this); 614 | switch ( getInterpreter().adaptivePredict(_input,4,_ctx) ) { 615 | case 1: 616 | { 617 | setState(69); 618 | match(Else); 619 | setState(70); 620 | ((IfStmtContext)_localctx).falseStmt = statement(); 621 | } 622 | break; 623 | } 624 | } 625 | break; 626 | case 4: 627 | _localctx = new ReturnStmtContext(_localctx); 628 | enterOuterAlt(_localctx, 4); 629 | { 630 | setState(73); 631 | match(Return); 632 | setState(75); 633 | _errHandler.sync(this); 634 | _la = _input.LA(1); 635 | if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << LeftParen) | (1L << Identifier) | (1L << DecimalInteger))) != 0)) { 636 | { 637 | setState(74); 638 | expression(0); 639 | } 640 | } 641 | 642 | setState(77); 643 | match(Semi); 644 | } 645 | break; 646 | case 5: 647 | _localctx = new PureExprStmtContext(_localctx); 648 | enterOuterAlt(_localctx, 5); 649 | { 650 | setState(78); 651 | expression(0); 652 | setState(79); 653 | match(Semi); 654 | } 655 | break; 656 | case 6: 657 | _localctx = new EmptyStmtContext(_localctx); 658 | enterOuterAlt(_localctx, 6); 659 | { 660 | setState(81); 661 | match(Semi); 662 | } 663 | break; 664 | } 665 | } 666 | catch (RecognitionException re) { 667 | _localctx.exception = re; 668 | _errHandler.reportError(this, re); 669 | _errHandler.recover(this, re); 670 | } 671 | finally { 672 | exitRule(); 673 | } 674 | return _localctx; 675 | } 676 | 677 | public static class ExpressionContext extends ParserRuleContext { 678 | public ExpressionContext(ParserRuleContext parent, int invokingState) { 679 | super(parent, invokingState); 680 | } 681 | @Override public int getRuleIndex() { return RULE_expression; } 682 | 683 | public ExpressionContext() { } 684 | public void copyFrom(ExpressionContext ctx) { 685 | super.copyFrom(ctx); 686 | } 687 | } 688 | public static class AtomExprContext extends ExpressionContext { 689 | public PrimaryContext primary() { 690 | return getRuleContext(PrimaryContext.class,0); 691 | } 692 | public AtomExprContext(ExpressionContext ctx) { copyFrom(ctx); } 693 | @Override 694 | public void enterRule(ParseTreeListener listener) { 695 | if ( listener instanceof YxListener ) ((YxListener)listener).enterAtomExpr(this); 696 | } 697 | @Override 698 | public void exitRule(ParseTreeListener listener) { 699 | if ( listener instanceof YxListener ) ((YxListener)listener).exitAtomExpr(this); 700 | } 701 | @Override 702 | public T accept(ParseTreeVisitor visitor) { 703 | if ( visitor instanceof YxVisitor ) return ((YxVisitor)visitor).visitAtomExpr(this); 704 | else return visitor.visitChildren(this); 705 | } 706 | } 707 | public static class BinaryExprContext extends ExpressionContext { 708 | public Token op; 709 | public List expression() { 710 | return getRuleContexts(ExpressionContext.class); 711 | } 712 | public ExpressionContext expression(int i) { 713 | return getRuleContext(ExpressionContext.class,i); 714 | } 715 | public TerminalNode Plus() { return getToken(YxParser.Plus, 0); } 716 | public TerminalNode Minus() { return getToken(YxParser.Minus, 0); } 717 | public TerminalNode Equal() { return getToken(YxParser.Equal, 0); } 718 | public TerminalNode NotEqual() { return getToken(YxParser.NotEqual, 0); } 719 | public BinaryExprContext(ExpressionContext ctx) { copyFrom(ctx); } 720 | @Override 721 | public void enterRule(ParseTreeListener listener) { 722 | if ( listener instanceof YxListener ) ((YxListener)listener).enterBinaryExpr(this); 723 | } 724 | @Override 725 | public void exitRule(ParseTreeListener listener) { 726 | if ( listener instanceof YxListener ) ((YxListener)listener).exitBinaryExpr(this); 727 | } 728 | @Override 729 | public T accept(ParseTreeVisitor visitor) { 730 | if ( visitor instanceof YxVisitor ) return ((YxVisitor)visitor).visitBinaryExpr(this); 731 | else return visitor.visitChildren(this); 732 | } 733 | } 734 | public static class AssignExprContext extends ExpressionContext { 735 | public List expression() { 736 | return getRuleContexts(ExpressionContext.class); 737 | } 738 | public ExpressionContext expression(int i) { 739 | return getRuleContext(ExpressionContext.class,i); 740 | } 741 | public TerminalNode Assign() { return getToken(YxParser.Assign, 0); } 742 | public AssignExprContext(ExpressionContext ctx) { copyFrom(ctx); } 743 | @Override 744 | public void enterRule(ParseTreeListener listener) { 745 | if ( listener instanceof YxListener ) ((YxListener)listener).enterAssignExpr(this); 746 | } 747 | @Override 748 | public void exitRule(ParseTreeListener listener) { 749 | if ( listener instanceof YxListener ) ((YxListener)listener).exitAssignExpr(this); 750 | } 751 | @Override 752 | public T accept(ParseTreeVisitor visitor) { 753 | if ( visitor instanceof YxVisitor ) return ((YxVisitor)visitor).visitAssignExpr(this); 754 | else return visitor.visitChildren(this); 755 | } 756 | } 757 | 758 | public final ExpressionContext expression() throws RecognitionException { 759 | return expression(0); 760 | } 761 | 762 | private ExpressionContext expression(int _p) throws RecognitionException { 763 | ParserRuleContext _parentctx = _ctx; 764 | int _parentState = getState(); 765 | ExpressionContext _localctx = new ExpressionContext(_ctx, _parentState); 766 | ExpressionContext _prevctx = _localctx; 767 | int _startState = 12; 768 | enterRecursionRule(_localctx, 12, RULE_expression, _p); 769 | int _la; 770 | try { 771 | int _alt; 772 | enterOuterAlt(_localctx, 1); 773 | { 774 | { 775 | _localctx = new AtomExprContext(_localctx); 776 | _ctx = _localctx; 777 | _prevctx = _localctx; 778 | 779 | setState(85); 780 | primary(); 781 | } 782 | _ctx.stop = _input.LT(-1); 783 | setState(98); 784 | _errHandler.sync(this); 785 | _alt = getInterpreter().adaptivePredict(_input,8,_ctx); 786 | while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { 787 | if ( _alt==1 ) { 788 | if ( _parseListeners!=null ) triggerExitRuleEvent(); 789 | _prevctx = _localctx; 790 | { 791 | setState(96); 792 | _errHandler.sync(this); 793 | switch ( getInterpreter().adaptivePredict(_input,7,_ctx) ) { 794 | case 1: 795 | { 796 | _localctx = new BinaryExprContext(new ExpressionContext(_parentctx, _parentState)); 797 | pushNewRecursionContext(_localctx, _startState, RULE_expression); 798 | setState(87); 799 | if (!(precpred(_ctx, 3))) throw new FailedPredicateException(this, "precpred(_ctx, 3)"); 800 | setState(88); 801 | ((BinaryExprContext)_localctx).op = _input.LT(1); 802 | _la = _input.LA(1); 803 | if ( !(_la==Plus || _la==Minus) ) { 804 | ((BinaryExprContext)_localctx).op = (Token)_errHandler.recoverInline(this); 805 | } 806 | else { 807 | if ( _input.LA(1)==Token.EOF ) matchedEOF = true; 808 | _errHandler.reportMatch(this); 809 | consume(); 810 | } 811 | setState(89); 812 | expression(4); 813 | } 814 | break; 815 | case 2: 816 | { 817 | _localctx = new BinaryExprContext(new ExpressionContext(_parentctx, _parentState)); 818 | pushNewRecursionContext(_localctx, _startState, RULE_expression); 819 | setState(90); 820 | if (!(precpred(_ctx, 2))) throw new FailedPredicateException(this, "precpred(_ctx, 2)"); 821 | setState(91); 822 | ((BinaryExprContext)_localctx).op = _input.LT(1); 823 | _la = _input.LA(1); 824 | if ( !(_la==Equal || _la==NotEqual) ) { 825 | ((BinaryExprContext)_localctx).op = (Token)_errHandler.recoverInline(this); 826 | } 827 | else { 828 | if ( _input.LA(1)==Token.EOF ) matchedEOF = true; 829 | _errHandler.reportMatch(this); 830 | consume(); 831 | } 832 | setState(92); 833 | expression(3); 834 | } 835 | break; 836 | case 3: 837 | { 838 | _localctx = new AssignExprContext(new ExpressionContext(_parentctx, _parentState)); 839 | pushNewRecursionContext(_localctx, _startState, RULE_expression); 840 | setState(93); 841 | if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)"); 842 | setState(94); 843 | match(Assign); 844 | setState(95); 845 | expression(1); 846 | } 847 | break; 848 | } 849 | } 850 | } 851 | setState(100); 852 | _errHandler.sync(this); 853 | _alt = getInterpreter().adaptivePredict(_input,8,_ctx); 854 | } 855 | } 856 | } 857 | catch (RecognitionException re) { 858 | _localctx.exception = re; 859 | _errHandler.reportError(this, re); 860 | _errHandler.recover(this, re); 861 | } 862 | finally { 863 | unrollRecursionContexts(_parentctx); 864 | } 865 | return _localctx; 866 | } 867 | 868 | public static class PrimaryContext extends ParserRuleContext { 869 | public TerminalNode LeftParen() { return getToken(YxParser.LeftParen, 0); } 870 | public ExpressionContext expression() { 871 | return getRuleContext(ExpressionContext.class,0); 872 | } 873 | public TerminalNode RightParen() { return getToken(YxParser.RightParen, 0); } 874 | public TerminalNode Identifier() { return getToken(YxParser.Identifier, 0); } 875 | public LiteralContext literal() { 876 | return getRuleContext(LiteralContext.class,0); 877 | } 878 | public PrimaryContext(ParserRuleContext parent, int invokingState) { 879 | super(parent, invokingState); 880 | } 881 | @Override public int getRuleIndex() { return RULE_primary; } 882 | @Override 883 | public void enterRule(ParseTreeListener listener) { 884 | if ( listener instanceof YxListener ) ((YxListener)listener).enterPrimary(this); 885 | } 886 | @Override 887 | public void exitRule(ParseTreeListener listener) { 888 | if ( listener instanceof YxListener ) ((YxListener)listener).exitPrimary(this); 889 | } 890 | @Override 891 | public T accept(ParseTreeVisitor visitor) { 892 | if ( visitor instanceof YxVisitor ) return ((YxVisitor)visitor).visitPrimary(this); 893 | else return visitor.visitChildren(this); 894 | } 895 | } 896 | 897 | public final PrimaryContext primary() throws RecognitionException { 898 | PrimaryContext _localctx = new PrimaryContext(_ctx, getState()); 899 | enterRule(_localctx, 14, RULE_primary); 900 | try { 901 | setState(107); 902 | _errHandler.sync(this); 903 | switch (_input.LA(1)) { 904 | case LeftParen: 905 | enterOuterAlt(_localctx, 1); 906 | { 907 | setState(101); 908 | match(LeftParen); 909 | setState(102); 910 | expression(0); 911 | setState(103); 912 | match(RightParen); 913 | } 914 | break; 915 | case Identifier: 916 | enterOuterAlt(_localctx, 2); 917 | { 918 | setState(105); 919 | match(Identifier); 920 | } 921 | break; 922 | case DecimalInteger: 923 | enterOuterAlt(_localctx, 3); 924 | { 925 | setState(106); 926 | literal(); 927 | } 928 | break; 929 | default: 930 | throw new NoViableAltException(this); 931 | } 932 | } 933 | catch (RecognitionException re) { 934 | _localctx.exception = re; 935 | _errHandler.reportError(this, re); 936 | _errHandler.recover(this, re); 937 | } 938 | finally { 939 | exitRule(); 940 | } 941 | return _localctx; 942 | } 943 | 944 | public static class LiteralContext extends ParserRuleContext { 945 | public TerminalNode DecimalInteger() { return getToken(YxParser.DecimalInteger, 0); } 946 | public LiteralContext(ParserRuleContext parent, int invokingState) { 947 | super(parent, invokingState); 948 | } 949 | @Override public int getRuleIndex() { return RULE_literal; } 950 | @Override 951 | public void enterRule(ParseTreeListener listener) { 952 | if ( listener instanceof YxListener ) ((YxListener)listener).enterLiteral(this); 953 | } 954 | @Override 955 | public void exitRule(ParseTreeListener listener) { 956 | if ( listener instanceof YxListener ) ((YxListener)listener).exitLiteral(this); 957 | } 958 | @Override 959 | public T accept(ParseTreeVisitor visitor) { 960 | if ( visitor instanceof YxVisitor ) return ((YxVisitor)visitor).visitLiteral(this); 961 | else return visitor.visitChildren(this); 962 | } 963 | } 964 | 965 | public final LiteralContext literal() throws RecognitionException { 966 | LiteralContext _localctx = new LiteralContext(_ctx, getState()); 967 | enterRule(_localctx, 16, RULE_literal); 968 | try { 969 | enterOuterAlt(_localctx, 1); 970 | { 971 | setState(109); 972 | match(DecimalInteger); 973 | } 974 | } 975 | catch (RecognitionException re) { 976 | _localctx.exception = re; 977 | _errHandler.reportError(this, re); 978 | _errHandler.recover(this, re); 979 | } 980 | finally { 981 | exitRule(); 982 | } 983 | return _localctx; 984 | } 985 | 986 | public static class TypeContext extends ParserRuleContext { 987 | public TerminalNode Int() { return getToken(YxParser.Int, 0); } 988 | public TerminalNode Identifier() { return getToken(YxParser.Identifier, 0); } 989 | public TypeContext(ParserRuleContext parent, int invokingState) { 990 | super(parent, invokingState); 991 | } 992 | @Override public int getRuleIndex() { return RULE_type; } 993 | @Override 994 | public void enterRule(ParseTreeListener listener) { 995 | if ( listener instanceof YxListener ) ((YxListener)listener).enterType(this); 996 | } 997 | @Override 998 | public void exitRule(ParseTreeListener listener) { 999 | if ( listener instanceof YxListener ) ((YxListener)listener).exitType(this); 1000 | } 1001 | @Override 1002 | public T accept(ParseTreeVisitor visitor) { 1003 | if ( visitor instanceof YxVisitor ) return ((YxVisitor)visitor).visitType(this); 1004 | else return visitor.visitChildren(this); 1005 | } 1006 | } 1007 | 1008 | public final TypeContext type() throws RecognitionException { 1009 | TypeContext _localctx = new TypeContext(_ctx, getState()); 1010 | enterRule(_localctx, 18, RULE_type); 1011 | int _la; 1012 | try { 1013 | enterOuterAlt(_localctx, 1); 1014 | { 1015 | setState(111); 1016 | _la = _input.LA(1); 1017 | if ( !(_la==Int || _la==Identifier) ) { 1018 | _errHandler.recoverInline(this); 1019 | } 1020 | else { 1021 | if ( _input.LA(1)==Token.EOF ) matchedEOF = true; 1022 | _errHandler.reportMatch(this); 1023 | consume(); 1024 | } 1025 | } 1026 | } 1027 | catch (RecognitionException re) { 1028 | _localctx.exception = re; 1029 | _errHandler.reportError(this, re); 1030 | _errHandler.recover(this, re); 1031 | } 1032 | finally { 1033 | exitRule(); 1034 | } 1035 | return _localctx; 1036 | } 1037 | 1038 | public boolean sempred(RuleContext _localctx, int ruleIndex, int predIndex) { 1039 | switch (ruleIndex) { 1040 | case 6: 1041 | return expression_sempred((ExpressionContext)_localctx, predIndex); 1042 | } 1043 | return true; 1044 | } 1045 | private boolean expression_sempred(ExpressionContext _localctx, int predIndex) { 1046 | switch (predIndex) { 1047 | case 0: 1048 | return precpred(_ctx, 3); 1049 | case 1: 1050 | return precpred(_ctx, 2); 1051 | case 2: 1052 | return precpred(_ctx, 1); 1053 | } 1054 | return true; 1055 | } 1056 | 1057 | public static final String _serializedATN = 1058 | "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3*t\4\2\t\2\4\3\t\3"+ 1059 | "\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t\13\3\2"+ 1060 | "\7\2\30\n\2\f\2\16\2\33\13\2\3\2\3\2\3\3\3\3\3\3\3\3\3\3\3\4\3\4\3\4\3"+ 1061 | "\4\5\4(\n\4\3\4\3\4\3\5\3\5\3\5\3\5\7\5\60\n\5\f\5\16\5\63\13\5\3\5\3"+ 1062 | "\5\3\5\3\6\3\6\7\6:\n\6\f\6\16\6=\13\6\3\6\3\6\3\7\3\7\3\7\3\7\3\7\3\7"+ 1063 | "\3\7\3\7\3\7\5\7J\n\7\3\7\3\7\5\7N\n\7\3\7\3\7\3\7\3\7\3\7\5\7U\n\7\3"+ 1064 | "\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\7\bc\n\b\f\b\16\bf\13\b"+ 1065 | "\3\t\3\t\3\t\3\t\3\t\3\t\5\tn\n\t\3\n\3\n\3\13\3\13\3\13\2\3\16\f\2\4"+ 1066 | "\6\b\n\f\16\20\22\24\2\5\3\2\25\26\3\2#$\4\2\4\4%%\2y\2\31\3\2\2\2\4\36"+ 1067 | "\3\2\2\2\6#\3\2\2\2\b+\3\2\2\2\n\67\3\2\2\2\fT\3\2\2\2\16V\3\2\2\2\20"+ 1068 | "m\3\2\2\2\22o\3\2\2\2\24q\3\2\2\2\26\30\5\b\5\2\27\26\3\2\2\2\30\33\3"+ 1069 | "\2\2\2\31\27\3\2\2\2\31\32\3\2\2\2\32\34\3\2\2\2\33\31\3\2\2\2\34\35\5"+ 1070 | "\4\3\2\35\3\3\2\2\2\36\37\7\4\2\2\37 \7\3\2\2 !\5\n\6\2!\"\7\2\2\3\"\5"+ 1071 | "\3\2\2\2#$\5\24\13\2$\'\7%\2\2%&\7\"\2\2&(\5\16\b\2\'%\3\2\2\2\'(\3\2"+ 1072 | "\2\2()\3\2\2\2)*\7 \2\2*\7\3\2\2\2+,\7\b\2\2,-\7%\2\2-\61\7\r\2\2.\60"+ 1073 | "\5\6\4\2/.\3\2\2\2\60\63\3\2\2\2\61/\3\2\2\2\61\62\3\2\2\2\62\64\3\2\2"+ 1074 | "\2\63\61\3\2\2\2\64\65\7\16\2\2\65\66\7 \2\2\66\t\3\2\2\2\67;\7\r\2\2"+ 1075 | "8:\5\f\7\298\3\2\2\2:=\3\2\2\2;9\3\2\2\2;<\3\2\2\2<>\3\2\2\2=;\3\2\2\2"+ 1076 | ">?\7\16\2\2?\13\3\2\2\2@U\5\n\6\2AU\5\6\4\2BC\7\5\2\2CD\7\t\2\2DE\5\16"+ 1077 | "\b\2EF\7\n\2\2FI\5\f\7\2GH\7\6\2\2HJ\5\f\7\2IG\3\2\2\2IJ\3\2\2\2JU\3\2"+ 1078 | "\2\2KM\7\7\2\2LN\5\16\b\2ML\3\2\2\2MN\3\2\2\2NO\3\2\2\2OU\7 \2\2PQ\5\16"+ 1079 | "\b\2QR\7 \2\2RU\3\2\2\2SU\7 \2\2T@\3\2\2\2TA\3\2\2\2TB\3\2\2\2TK\3\2\2"+ 1080 | "\2TP\3\2\2\2TS\3\2\2\2U\r\3\2\2\2VW\b\b\1\2WX\5\20\t\2Xd\3\2\2\2YZ\f\5"+ 1081 | "\2\2Z[\t\2\2\2[c\5\16\b\6\\]\f\4\2\2]^\t\3\2\2^c\5\16\b\5_`\f\3\2\2`a"+ 1082 | "\7\"\2\2ac\5\16\b\3bY\3\2\2\2b\\\3\2\2\2b_\3\2\2\2cf\3\2\2\2db\3\2\2\2"+ 1083 | "de\3\2\2\2e\17\3\2\2\2fd\3\2\2\2gh\7\t\2\2hi\5\16\b\2ij\7\n\2\2jn\3\2"+ 1084 | "\2\2kn\7%\2\2ln\5\22\n\2mg\3\2\2\2mk\3\2\2\2ml\3\2\2\2n\21\3\2\2\2op\7"+ 1085 | "&\2\2p\23\3\2\2\2qr\t\4\2\2r\25\3\2\2\2\f\31\'\61;IMTbdm"; 1086 | public static final ATN _ATN = 1087 | new ATNDeserializer().deserialize(_serializedATN.toCharArray()); 1088 | static { 1089 | _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; 1090 | for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) { 1091 | _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); 1092 | } 1093 | } 1094 | } -------------------------------------------------------------------------------- /src/Parser/YxVisitor.java: -------------------------------------------------------------------------------- 1 | // Generated from Yx.g4 by ANTLR 4.7.2 2 | package Parser; 3 | import org.antlr.v4.runtime.tree.ParseTreeVisitor; 4 | 5 | /** 6 | * This interface defines a complete generic visitor for a parse tree produced 7 | * by {@link YxParser}. 8 | * 9 | * @param The return type of the visit operation. Use {@link Void} for 10 | * operations with no return type. 11 | */ 12 | public interface YxVisitor extends ParseTreeVisitor { 13 | /** 14 | * Visit a parse tree produced by {@link YxParser#program}. 15 | * @param ctx the parse tree 16 | * @return the visitor result 17 | */ 18 | T visitProgram(YxParser.ProgramContext ctx); 19 | /** 20 | * Visit a parse tree produced by {@link YxParser#mainFn}. 21 | * @param ctx the parse tree 22 | * @return the visitor result 23 | */ 24 | T visitMainFn(YxParser.MainFnContext ctx); 25 | /** 26 | * Visit a parse tree produced by {@link YxParser#varDef}. 27 | * @param ctx the parse tree 28 | * @return the visitor result 29 | */ 30 | T visitVarDef(YxParser.VarDefContext ctx); 31 | /** 32 | * Visit a parse tree produced by {@link YxParser#classDef}. 33 | * @param ctx the parse tree 34 | * @return the visitor result 35 | */ 36 | T visitClassDef(YxParser.ClassDefContext ctx); 37 | /** 38 | * Visit a parse tree produced by {@link YxParser#suite}. 39 | * @param ctx the parse tree 40 | * @return the visitor result 41 | */ 42 | T visitSuite(YxParser.SuiteContext ctx); 43 | /** 44 | * Visit a parse tree produced by the {@code block} 45 | * labeled alternative in {@link YxParser#statement}. 46 | * @param ctx the parse tree 47 | * @return the visitor result 48 | */ 49 | T visitBlock(YxParser.BlockContext ctx); 50 | /** 51 | * Visit a parse tree produced by the {@code vardefStmt} 52 | * labeled alternative in {@link YxParser#statement}. 53 | * @param ctx the parse tree 54 | * @return the visitor result 55 | */ 56 | T visitVardefStmt(YxParser.VardefStmtContext ctx); 57 | /** 58 | * Visit a parse tree produced by the {@code ifStmt} 59 | * labeled alternative in {@link YxParser#statement}. 60 | * @param ctx the parse tree 61 | * @return the visitor result 62 | */ 63 | T visitIfStmt(YxParser.IfStmtContext ctx); 64 | /** 65 | * Visit a parse tree produced by the {@code returnStmt} 66 | * labeled alternative in {@link YxParser#statement}. 67 | * @param ctx the parse tree 68 | * @return the visitor result 69 | */ 70 | T visitReturnStmt(YxParser.ReturnStmtContext ctx); 71 | /** 72 | * Visit a parse tree produced by the {@code pureExprStmt} 73 | * labeled alternative in {@link YxParser#statement}. 74 | * @param ctx the parse tree 75 | * @return the visitor result 76 | */ 77 | T visitPureExprStmt(YxParser.PureExprStmtContext ctx); 78 | /** 79 | * Visit a parse tree produced by the {@code emptyStmt} 80 | * labeled alternative in {@link YxParser#statement}. 81 | * @param ctx the parse tree 82 | * @return the visitor result 83 | */ 84 | T visitEmptyStmt(YxParser.EmptyStmtContext ctx); 85 | /** 86 | * Visit a parse tree produced by the {@code atomExpr} 87 | * labeled alternative in {@link YxParser#expression}. 88 | * @param ctx the parse tree 89 | * @return the visitor result 90 | */ 91 | T visitAtomExpr(YxParser.AtomExprContext ctx); 92 | /** 93 | * Visit a parse tree produced by the {@code binaryExpr} 94 | * labeled alternative in {@link YxParser#expression}. 95 | * @param ctx the parse tree 96 | * @return the visitor result 97 | */ 98 | T visitBinaryExpr(YxParser.BinaryExprContext ctx); 99 | /** 100 | * Visit a parse tree produced by the {@code assignExpr} 101 | * labeled alternative in {@link YxParser#expression}. 102 | * @param ctx the parse tree 103 | * @return the visitor result 104 | */ 105 | T visitAssignExpr(YxParser.AssignExprContext ctx); 106 | /** 107 | * Visit a parse tree produced by {@link YxParser#primary}. 108 | * @param ctx the parse tree 109 | * @return the visitor result 110 | */ 111 | T visitPrimary(YxParser.PrimaryContext ctx); 112 | /** 113 | * Visit a parse tree produced by {@link YxParser#literal}. 114 | * @param ctx the parse tree 115 | * @return the visitor result 116 | */ 117 | T visitLiteral(YxParser.LiteralContext ctx); 118 | /** 119 | * Visit a parse tree produced by {@link YxParser#type}. 120 | * @param ctx the parse tree 121 | * @return the visitor result 122 | */ 123 | T visitType(YxParser.TypeContext ctx); 124 | } -------------------------------------------------------------------------------- /src/Util/Scope.java: -------------------------------------------------------------------------------- 1 | package Util; 2 | 3 | import MIR.register; 4 | import Util.error.semanticError; 5 | 6 | import java.util.HashMap; 7 | 8 | public class Scope { 9 | 10 | private HashMap members; 11 | public HashMap entities = new HashMap<>(); 12 | private Scope parentScope; 13 | 14 | 15 | public Scope(Scope parentScope) { 16 | members = new HashMap<>(); 17 | this.parentScope = parentScope; 18 | } 19 | 20 | public Scope parentScope() { 21 | return parentScope; 22 | } 23 | 24 | public void defineVariable(String name, Type t, position pos) { 25 | if (members.containsKey(name)) 26 | throw new semanticError("Semantic Error: variable redefine", pos); 27 | members.put(name, t); 28 | } 29 | 30 | public boolean containsVariable(String name, boolean lookUpon) { 31 | if (members.containsKey(name)) return true; 32 | else if (parentScope != null && lookUpon) 33 | return parentScope.containsVariable(name, true); 34 | else return false; 35 | } 36 | public Type getType(String name, boolean lookUpon) { 37 | if (members.containsKey(name)) return members.get(name); 38 | else if (parentScope != null && lookUpon) 39 | return parentScope.getType(name, true); 40 | return null; 41 | } 42 | public register getEntity(String name, boolean lookUpon) { 43 | if (entities.containsKey(name)) return entities.get(name); 44 | else if (parentScope != null && lookUpon) 45 | return parentScope.getEntity(name, true); 46 | return null; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Util/Type.java: -------------------------------------------------------------------------------- 1 | package Util; 2 | 3 | import java.util.HashMap; 4 | 5 | public class Type { 6 | public boolean isInt = false, isBool = false; 7 | public HashMap members = null; 8 | } 9 | -------------------------------------------------------------------------------- /src/Util/YxErrorListener.java: -------------------------------------------------------------------------------- 1 | package Util; 2 | 3 | import Util.error.syntaxError; 4 | import Util.position; 5 | import org.antlr.v4.runtime.BaseErrorListener; 6 | import org.antlr.v4.runtime.RecognitionException; 7 | import org.antlr.v4.runtime.Recognizer; 8 | 9 | public class YxErrorListener extends BaseErrorListener { 10 | @Override 11 | public void syntaxError(Recognizer recognizer, 12 | Object offendingSymbol, 13 | int line, int charPositionInLine, 14 | String msg, 15 | RecognitionException e) { 16 | 17 | throw new syntaxError(msg, new position(line, charPositionInLine)); 18 | } 19 | } -------------------------------------------------------------------------------- /src/Util/error/error.java: -------------------------------------------------------------------------------- 1 | package Util.error; 2 | import Util.position; 3 | 4 | abstract public class error extends RuntimeException { 5 | private position pos; 6 | private String message; 7 | 8 | public error(String msg, position pos) { 9 | this.pos = pos; 10 | this.message = msg; 11 | } 12 | 13 | public String toString() { 14 | return message + ": " + pos.toString(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Util/error/internalError.java: -------------------------------------------------------------------------------- 1 | package Util.error; 2 | import Util.position; 3 | 4 | public class internalError extends error { 5 | 6 | public internalError(String msg, position pos) { 7 | super("Internal Error:" + msg, pos); 8 | } 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/Util/error/semanticError.java: -------------------------------------------------------------------------------- 1 | package Util.error; 2 | import Util.position; 3 | 4 | public class semanticError extends error { 5 | 6 | public semanticError(String msg, position pos) { 7 | super("Semantic Error: " + msg, pos); 8 | } 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/Util/error/syntaxError.java: -------------------------------------------------------------------------------- 1 | package Util.error; 2 | import Util.position; 3 | 4 | public class syntaxError extends error { 5 | 6 | public syntaxError(String msg, position pos) { 7 | super("SyntaxError: " + msg, pos); 8 | } 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/Util/globalScope.java: -------------------------------------------------------------------------------- 1 | package Util; 2 | 3 | import Util.error.semanticError; 4 | 5 | import java.util.HashMap; 6 | 7 | public class globalScope extends Scope { 8 | private HashMap types = new HashMap<>(); 9 | public globalScope(Scope parentScope) { 10 | super(parentScope); 11 | } 12 | public void addType(String name, Type t, position pos) { 13 | if (types.containsKey(name)) 14 | throw new semanticError("multiple definition of " + name, pos); 15 | types.put(name, t); 16 | } 17 | public Type getTypeFromName(String name, position pos) { 18 | if (types.containsKey(name)) return types.get(name); 19 | throw new semanticError("no such type: " + name, pos); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Util/position.java: -------------------------------------------------------------------------------- 1 | package Util; 2 | 3 | import org.antlr.v4.runtime.ParserRuleContext; 4 | import org.antlr.v4.runtime.Token; 5 | import org.antlr.v4.runtime.tree.TerminalNode; 6 | 7 | public class position { 8 | private int row, column; 9 | 10 | public position(int row, int col) { 11 | this.row = row; 12 | this.column = col; 13 | } 14 | 15 | public position(Token token) { 16 | this.row = token.getLine(); 17 | this.column = token.getCharPositionInLine(); 18 | } 19 | 20 | public position(TerminalNode terminal) { 21 | this(terminal.getSymbol()); 22 | } 23 | 24 | public position(ParserRuleContext ctx) { 25 | this(ctx.getStart()); 26 | } 27 | 28 | public int row() { return row; } 29 | 30 | public int col() { 31 | return column; 32 | } 33 | 34 | public String toString() { return row + "," + column; } 35 | } 36 | -------------------------------------------------------------------------------- /testcases/correct.yx: -------------------------------------------------------------------------------- 1 | struct A { 2 | int a; 3 | }; 4 | int main(){ 5 | int a=1; 6 | int b=2; 7 | int c=3; 8 | A x; 9 | A y; 10 | 11 | { 12 | a=b+c; 13 | b==a+c; 14 | if(a==b+c){ 15 | a=b-(c+2); 16 | }else{ 17 | a=b-(2-c); 18 | } 19 | int b = 0; 20 | if ((a == b) == (a == c)) a = 1; 21 | if (x != y) x = y; 22 | } 23 | return (a+b)+c; 24 | } -------------------------------------------------------------------------------- /testcases/wrong1 - int not match.yx: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a=1; 3 | int b=2; 4 | int c=a==b; 5 | return c; 6 | } -------------------------------------------------------------------------------- /testcases/wrong2 - bool not match.yx: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a=2; 3 | if(1){ 4 | a=3; 5 | } 6 | return a; 7 | 8 | } -------------------------------------------------------------------------------- /testcases/wrong3 - variable undefined.yx: -------------------------------------------------------------------------------- 1 | int main(){ 2 | { 3 | int a=1; 4 | if(a==2){ 5 | a=a+1; 6 | }else{ 7 | a=a-1; 8 | } 9 | } 10 | return a; 11 | } -------------------------------------------------------------------------------- /testcases/wrong4 - multi definition.yx: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a=1; 3 | if(a==2){ 4 | a=a+1; 5 | }else{ 6 | a=a-1; 7 | } 8 | int a; 9 | return a; 10 | } --------------------------------------------------------------------------------