Advertisement
Guest User

Untitled

a guest
Apr 23rd, 2017
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.23 KB | None | 0 0
  1.  
  2. /**
  3. * Copyright 1997-2015 Stefan Nilsson, 2015-2017 Douglas Wikstrom.
  4. * This file is part of the NIC/NAS software licensed under BSD
  5. * License 2.0. See LICENSE file.
  6. */
  7.  
  8. package se.kth.csc.nas;
  9.  
  10. import java.io.BufferedReader;
  11. import java.io.IOException;
  12. import java.io.StringReader;
  13. import java.util.ArrayList;
  14. import java.util.Arrays;
  15. import java.util.List;
  16.  
  17. /**
  18. * Parser for assembler source files.
  19. */
  20. public class Parser {
  21.  
  22. /**
  23. * Number of bits in each block.
  24. */
  25. final static int BLOCKSIZE = 4;
  26.  
  27. /**
  28. * Lines of source code.
  29. */
  30. final List<String> lines;
  31.  
  32. /**
  33. * Error log.
  34. */
  35. final ErrorLog errorLog;
  36.  
  37. /**
  38. * Table of symbols.
  39. */
  40. final SymbolTable symbolTable;
  41.  
  42. /**
  43. * List of instructions.
  44. */
  45. final InstructionList instructionList;
  46.  
  47. /**
  48. * Lexical analyzer.
  49. */
  50. final Lex lex;
  51.  
  52. /**
  53. * Creates a parser with the given error log.
  54. *
  55. * @param maxErrors Maximal number of errors logged before
  56. * aborting.
  57. */
  58. public Parser(final int maxErrors) {
  59. this.lines = new ArrayList<String>();
  60. this.errorLog = new ErrorLog(lines, maxErrors);
  61. this.symbolTable = new SymbolTable();
  62. this.instructionList = new InstructionList(errorLog);
  63. this.lex = new Lex(BLOCKSIZE, errorLog);
  64. }
  65.  
  66. /**
  67. * Parses a label and stores it in the symbol table.
  68. *
  69. * @param s String expected to be a label.
  70. */
  71. void parseLabel(final String s) {
  72.  
  73. if (symbolTable.get(s) == null) {
  74.  
  75. if (lex.isIdentifier(s)) {
  76. final Symbol symbol = new Symbol(SymbolType.LABEL, s);
  77. symbol.setAddress(4 * instructionList.size());
  78. symbolTable.put(symbol);
  79. } else {
  80. errorLog.error("Invalid name! (%s)", s);
  81. }
  82. } else {
  83. errorLog.error("Name already defined! (%s)", s);
  84. }
  85. }
  86.  
  87. /**
  88. * Parses operators that take no arguments.
  89. *
  90. * @param operator Operator.
  91. * @param tokens Parameters (should only contain the name of the
  92. * operator).
  93. */
  94. void parseNoArgs(final Operator operator, final String[] tokens) {
  95. if (tokens.length == 1) {
  96.  
  97. int t;
  98. System.out.println("3");
  99. switch (operator) {
  100.  
  101. case HALT:
  102. t = 0;
  103. break;
  104. case NOOP:
  105. t = 1;
  106. break;
  107. default:
  108. throw new Error("Illegal invocation! This is a bug!");
  109. }
  110.  
  111. final Instruction ins =
  112. new Instruction(lines.size(), operator, 0, 0, t, null);
  113. instructionList.add(ins);
  114.  
  115. } else if (tokens.length > 1) {
  116.  
  117. errorLog.error("Unexpected operand! (%s)", tokens[1]);
  118. } else {
  119.  
  120. throw new Error("Illegal invocation! This is a bug!");
  121. }
  122. }
  123.  
  124. /**
  125. * Parses a value that may either be a hexidecimal or decimal
  126. * constant, or defined relative a symbolic address. In the latter
  127. * case the result is an offset symbolic value. This can be loaded
  128. * into a register or used as an address.
  129. *
  130. * @param s String representation of a value.
  131. * @return Constant or symbolic value defined using an offset.
  132. */
  133. Value parseValue(final String s) {
  134.  
  135. int n = 0;
  136. String name = "";
  137. int offset = 0;
  138.  
  139. final char first = s.charAt(0);
  140.  
  141. // Decimal and hexadecimal constant values start with '-' or a
  142. // decimal digit.
  143. if (first == '-' || ('0' <= first && first <= '9')) {
  144.  
  145. n = lex.parseIntBounded(s, 2);
  146.  
  147. // Symbolic value, or symbolic value with offset.
  148. } else {
  149.  
  150. final int middle = Math.max(s.indexOf("+"), s.indexOf("-"));
  151.  
  152. if (middle >= 0) {
  153. name = s.substring(0, middle);
  154.  
  155. String oString;
  156. if (s.charAt(middle) == '-') {
  157. oString = s.substring(middle);
  158. } else {
  159. oString = s.substring(middle + 1);
  160. }
  161. offset = lex.parseDecBounded(oString, 2);
  162.  
  163. } else {
  164. name = s;
  165. }
  166. }
  167.  
  168. // Can never be converted to a value.
  169. if (n == NAS.INT_ERR || offset == NAS.INT_ERR) {
  170. return null;
  171.  
  172. // Constant value or symbolic value (assuming that the name is
  173. // associated with a value.
  174. } else if (name.equals("") || lex.isIdentifier(name)) {
  175.  
  176. return new Value(name, n, offset);
  177.  
  178. // Name is not an identifier at all and can not be associated
  179. // with a value anywhere else.
  180. } else {
  181. errorLog.error("Invalid name! (%s)", name);
  182. return null;
  183. }
  184. }
  185.  
  186. /**
  187. * Parses an unconditional jump instruction.
  188. *
  189. * @param operator Jump operator.
  190. * @param tokens Parameters (must be a single value).
  191. */
  192. void parseJump(final Operator operator, final String[] tokens) {
  193. System.out.println("3");
  194. if (tokens.length == 2) {
  195.  
  196. final Value v = parseValue(tokens[1]);
  197. if (v == null) {
  198. return;
  199. } else {
  200. v.useHexFormat();
  201. final Instruction ins =
  202. new Instruction(lines.size(), operator, 0, 0, 0, v);
  203. instructionList.add(ins);
  204. }
  205. } else {
  206. errorLog.error("Need exactly one value after operator! (%s)",
  207. operator.toString());
  208. }
  209. }
  210.  
  211. /**
  212. * Parses an operator that takes a register and a value as
  213. * parameters.
  214. *
  215. * @param operator Operator.
  216. * @param tokens Parameters to operator.
  217. */
  218. void parseRegValue(final Operator operator, final String[] tokens) {
  219. System.out.println("3'");
  220. if (tokens.length == 3) {
  221.  
  222. final int r = lex.parseReg(tokens[1]);
  223. final Value v = parseValue(tokens[2]);
  224.  
  225. if (r == NAS.INT_ERR || v == null) {
  226. return;
  227. } else {
  228.  
  229. // Print addresses in hexadecimal format.
  230. switch (operator) {
  231. case LOAD:
  232. case STORE:
  233. case JUMPE:
  234. case JUMPN:
  235. case JUMPL:
  236. case JUMPLE:
  237. v.useHexFormat();
  238. break;
  239. }
  240.  
  241. final Instruction ins =
  242. new Instruction(lines.size(), operator, r, 0, 0, v);
  243. instructionList.add(ins);
  244. }
  245. } else {
  246. errorLog.error("Need register and value after operator! (%s)",
  247. operator.toString());
  248. }
  249. }
  250.  
  251. /**
  252. * Parses an operator that takes two registers as parameters.
  253. *
  254. * @param operator Operator.
  255. * @param tokens Parameters to operator.
  256. */
  257. void parseRegReg(final Operator operator, final String[] tokens) {
  258. if (tokens.length == 3) {
  259. System.out.println(operator);
  260. String operator_strang=operator+"";
  261. int q = 0;
  262.  
  263.  
  264.  
  265. // Här behöver ajg lägga till ett villkor beroende av vilken operator som kommer in, vilket tal 1 eller 0 som går ut
  266. switch(operator){
  267. case INV:
  268. System.out.println("!!!!!!!!!");
  269. q++;
  270. break; }
  271. /*case INV:
  272. System.out.println("?????");
  273. int q=1;
  274. break;
  275. }
  276. final int q=1;*/
  277. System.out.println(q + "Jippie");
  278.  
  279. final int r = lex.parseReg(tokens[1]);
  280. final int s = lex.parseReg(tokens[2]);
  281. System.out.println("-----");
  282. System.out.println(r+"");
  283. System.out.println(lines.size()+"regreg");
  284. // Gör om från hexadecimal till vanlig nummer 1-15
  285.  
  286. if (r != NAS.INT_ERR && s != NAS.INT_ERR) {
  287. // Här sätter vi ett villkor operator, 0, r, s, null)
  288. final Instruction ins =
  289. new Instruction(lines.size()+2, operator, q, r, s, null);
  290. instructionList.add(ins); // Skapar en ny instruktion som vi lägger till i instruktionlist
  291. }
  292. } else {
  293. errorLog.error("Need two registers after operator! (%s)",
  294. operator.toString());
  295. }
  296. }
  297.  
  298. /**
  299. * Parses an operator that takes three registers as parameters.
  300. *
  301. * @param operator Operator.
  302. * @param tokens Parameters to operator.
  303. */
  304. void parseRegRegReg(final Operator operator, final String[] tokens) {
  305. System.out.println("3");
  306. if (tokens.length == 4) {
  307. System.out.println(lines.size()+"regregreg");
  308. final int r = lex.parseReg(tokens[1]);
  309. final int s = lex.parseReg(tokens[2]);
  310. final int t = lex.parseReg(tokens[3]);
  311.  
  312. if (r != NAS.INT_ERR && s != NAS.INT_ERR && t != NAS.INT_ERR) {
  313. final Instruction ins =
  314. new Instruction(lines.size(), operator, r, s, t, null);
  315. instructionList.add(ins);
  316. }
  317. } else {
  318. errorLog.error("Need three registers after operator! (%s)",
  319. operator.toString());
  320. }
  321. }
  322.  
  323. /**
  324. * Parses an instruction.
  325. *
  326. * @param operator Operator.
  327. * @param tokens Parameters to operator.
  328. */
  329. void parseInstruction(final Operator operator, final String[] tokens) {
  330. System.out.println("2");
  331. switch (operator) {
  332.  
  333. // Operators taking no arguments.
  334. case NOOP:
  335. case HALT:
  336. parseNoArgs(operator, tokens);
  337. break;
  338. case JUMP:
  339. parseJump(operator, tokens);
  340. break;
  341. case LOAD:
  342. case LOADC:
  343. case STORE:
  344. case ADDC:
  345. case JUMPE:
  346. case JUMPN:
  347. case JUMPL:
  348. case JUMPLE:
  349. parseRegValue(operator, tokens);
  350. break;
  351. case LOADR:
  352. case STORER:
  353. case MOVE:
  354. case INV: // Våran
  355. parseRegReg(operator, tokens);
  356. break;
  357. default:
  358. parseRegRegReg(operator, tokens);
  359. break;
  360. }
  361. }
  362.  
  363. /**
  364. * Parses the values following a directive and returns the
  365. * corresponding integer values. If no values are given, then an
  366. * array of length one containing the zero value is
  367. * returned. Invalid values are replaced by zero.
  368. *
  369. * @param type Type of directive, which must be word or code.
  370. * @param tokens Tokens on input line.
  371. */
  372. int[] parseDirectiveValues(final SymbolType type, final String[] tokens) {
  373.  
  374. final int noValues = Math.max(tokens.length - 2, 1);
  375. final int[] values = new int[noValues];
  376.  
  377. for (int i = 2; i < tokens.length; i++) {
  378.  
  379. int n;
  380. if (type == SymbolType.WORD) {
  381. n = lex.parseIntBounded(tokens[i], 2);
  382. } else { // CODE
  383. n = lex.parseIntBounded(tokens[i], 4);
  384. }
  385.  
  386. values[i - 2] = (n != NAS.INT_ERR) ? n : 0;
  387. }
  388. return values;
  389. }
  390.  
  391. /**
  392. * Parse variable number of values for a word/code directive.
  393. *
  394. * @param type Type of symbol, which must be either word or code.
  395. * @param tokens Tokens on the line.
  396. */
  397. void parseDirective(final SymbolType type, final String[] tokens) {
  398. if (tokens.length < 2) {
  399. final String e =
  400. String.format("Need name after directive! (%s)", tokens[0]);
  401. errorLog.error(e);
  402. return;
  403. }
  404.  
  405. final String name = tokens[1];
  406.  
  407. if (symbolTable.get(name) == null) {
  408.  
  409. if (lex.isIdentifier(name)) {
  410.  
  411. final int[] values = parseDirectiveValues(type, tokens);
  412. final Symbol symbol = new Symbol(type, name, values);
  413. symbolTable.put(symbol);
  414.  
  415. } else {
  416. errorLog.error("Invalid name!", name);
  417. }
  418. } else {
  419. errorLog.error("Name already defined", name);
  420. }
  421. }
  422.  
  423. /**
  424. * Parses the given line and updates the symbol table or
  425. * instruction list.
  426. *
  427. * @param line Line of input.
  428. */
  429. void parseLine(final String[] tokens) {
  430.  
  431. String[] ctokens = tokens;
  432. String first = ctokens[0];
  433.  
  434. // Does the line contain a leading label?
  435. if (first.endsWith(":")) {
  436.  
  437. parseLabel(first.substring(0, first.length() - 1));
  438.  
  439. // Labels may preceed other content, so we need to leave
  440. // the rest in place if any as if there was no label.
  441. if (tokens.length > 1) {
  442. ctokens = Arrays.copyOfRange(tokens, 1, tokens.length);
  443. first = ctokens[0];
  444. } else {
  445. return;
  446. }
  447. }
  448.  
  449. // Parse word, code directive, or an instruction line.
  450. if (first.equals(SymbolType.WORD.name)) {
  451.  
  452. parseDirective(SymbolType.WORD, ctokens);
  453.  
  454. } else if (first.equals(SymbolType.CODE.name)) {
  455.  
  456. parseDirective(SymbolType.CODE, ctokens);
  457.  
  458. } else {
  459.  
  460. final Operator operator = Operators.get(first);
  461. if (operator == null) {
  462. errorLog.error("Unknown instruction! (%s)", first);
  463. } else {
  464. parseInstruction(operator, ctokens);
  465. }
  466. }
  467. }
  468.  
  469. /**
  470. * Parses the assembler program.
  471. *
  472. * @param source Assembler source.
  473. */
  474. public IntermediateFormat parse(final BufferedReader source)
  475. throws IOException {
  476.  
  477. String line = source.readLine();
  478.  
  479. try {
  480. while (line != null) {
  481. lines.add(line);
  482.  
  483. String[] tokens = lex.tokenizeLine(line);
  484. if (tokens != null) {
  485. parseLine(tokens);
  486. }
  487. line = source.readLine();
  488. }
  489. } catch (TooManyErrorsException tmee) {
  490. }
  491.  
  492. return new IntermediateFormat(lines, errorLog, symbolTable,
  493. instructionList);
  494. }
  495.  
  496. /**
  497. * Parses the assembler program and returns the resulting symbol
  498. * table and list of instructions.
  499. *
  500. * @param source Assembler source.
  501. */
  502. public IntermediateFormat parse(final String source) throws IOException {
  503. final StringReader sr = new StringReader(source);
  504. BufferedReader br = null;
  505. IntermediateFormat inf = null;
  506. try {
  507. br = new BufferedReader(sr);
  508. inf = parse(br);
  509. } catch (final IOException ioe) {
  510. errorLog.error(ioe, "Unable to read from source string!");
  511. } finally {
  512. if (br != null) {
  513. br.close();
  514. }
  515. }
  516. return inf;
  517. }
  518. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement