From fed70f3ac817ed4943a230cb901fcd65dc6fdd0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Gassmann?= Date: Fri, 11 Jun 2021 20:55:12 +0200 Subject: [~] First totaly functional Calculator, reorganised the files, verified and added error messages --- .../main/java/ch/bfh/lexer/CalculatorLexer.java | 105 +++++++++++++++++++++ .../src/main/java/ch/bfh/lexer/LexerException.java | 5 + .../src/main/java/ch/bfh/lexer/Token.java | 23 +++++ 3 files changed, 133 insertions(+) create mode 100644 calculator-java/src/main/java/ch/bfh/lexer/CalculatorLexer.java create mode 100644 calculator-java/src/main/java/ch/bfh/lexer/LexerException.java create mode 100644 calculator-java/src/main/java/ch/bfh/lexer/Token.java (limited to 'calculator-java/src/main/java/ch/bfh/lexer') diff --git a/calculator-java/src/main/java/ch/bfh/lexer/CalculatorLexer.java b/calculator-java/src/main/java/ch/bfh/lexer/CalculatorLexer.java new file mode 100644 index 0000000..0ba9535 --- /dev/null +++ b/calculator-java/src/main/java/ch/bfh/lexer/CalculatorLexer.java @@ -0,0 +1,105 @@ +package ch.bfh.lexer; + +// Lexer for classical arithmetic expressions with identifiers and assignments. +// Scans a source string char by char. + +public class CalculatorLexer { + + private String src; // source string for lexical analysis + private int idx; // current index in source + private int len; // length of source + + public CalculatorLexer() { } + + public void initLexer(String source) { + this.src = source; + idx = 0; + len = src.length(); + } + + // Consumes letters only and builds an identifier + private String identifier() { + StringBuffer s = new StringBuffer(); + + do { + s.append(src.charAt(idx)); + idx++; + } while (idx < len && Character.isLetter(src.charAt(idx))); + return s.toString(); + } + + // Consumes digits and convert integer part and decimal part + // Convert characters using the formula + // "3456.253" = [(((3+0)*10+4)*10+5)*10+6]+[0.1*2+0.01*5+0.001*3] + private double number() throws LexerException { + double v = 0; // accumulates the result + double factor = 0.1; // factor for decimal part + + do { // integer part + v = v * 10 + Character.digit(src.charAt(idx),30); + idx++; + } while (idx < len && Character.isDigit(src.charAt(idx))); + if (idx < len && src.charAt(idx) == '.') { // decimal point + idx++; + if (idx < len && Character.isDigit(src.charAt(idx))) { // decimal part + while (idx < len && Character.isDigit(src.charAt(idx))) { + v = v + (factor * Character.digit(src.charAt(idx),30)); + factor = factor * 0.1; + idx++; + } + } + else throw new LexerException("Illegal number: decimal part missing"); + } + return v; + } + + // Skips blanks, tabs, newlines + private void skip() { + char c; + while (idx < len) { + c = src.charAt(idx); + if (c==' ' || c=='\t' || c=='\n') idx++; + else break; + } + } + + // returns next token + public Token nextToken() throws LexerException { + Token tok = new Token(); + + skip(); + if (idx>=len) { + tok.str="EOL"; + tok.type=Token.EOL; + } + else + // is it a positive number? + if (Character.isDigit(src.charAt(idx))) { + tok.value = number(); + tok.type = Token.NUM; + tok.str = Double.toString(tok.value); + } + else + if (Character.isLetter(src.charAt(idx))) { + tok.value = 0; + tok.type = Token.ID; + tok.str = identifier(); + if (tok.str.compareTo("let")==0) tok.type = Token.LET; + if (tok.str.compareTo("exit")==0) tok.type = Token.END; + } + else { + switch (src.charAt(idx)) { + case '+': tok.type = Token.ADD; tok.str = "+"; break; + case '-': tok.type = Token.SUB; tok.str = "-"; break; + case '*': tok.type = Token.MUL; tok.str = "*"; break; + case '/': tok.type = Token.DIV; tok.str = "/"; break; + case '(': tok.type = Token.PAL; tok.str = "("; break; + case ')': tok.type = Token.PAR; tok.str = ")"; break; + case '=': tok.type = Token.EQU; tok.str = "="; break; + default : throw new LexerException("Illegal Token: '" + src.charAt(idx) + "'"); + } + idx++; + } + return tok; + } +} \ No newline at end of file diff --git a/calculator-java/src/main/java/ch/bfh/lexer/LexerException.java b/calculator-java/src/main/java/ch/bfh/lexer/LexerException.java new file mode 100644 index 0000000..c5f8671 --- /dev/null +++ b/calculator-java/src/main/java/ch/bfh/lexer/LexerException.java @@ -0,0 +1,5 @@ +package ch.bfh.lexer; + +public class LexerException extends RuntimeException { + public LexerException(String s) { super(s); } +} \ No newline at end of file diff --git a/calculator-java/src/main/java/ch/bfh/lexer/Token.java b/calculator-java/src/main/java/ch/bfh/lexer/Token.java new file mode 100644 index 0000000..b021075 --- /dev/null +++ b/calculator-java/src/main/java/ch/bfh/lexer/Token.java @@ -0,0 +1,23 @@ +package ch.bfh.lexer; + +// Various Tokens for arithmetic expressions based on integers +// with identifiers and assignments + +public class Token { + public int type; // token type + public double value; // numerical value for NUM + public String str; // token string + + public static final int EOL=0;// // End Of Line + public static final int PAL=1;// // Left Parenthesis + public static final int PAR=2;// // Right Parenthesis + public static final int ADD=3;// // operators + public static final int SUB=4;// + public static final int MUL=5; + public static final int DIV=6; + public static final int NUM=7;// // number + public static final int EQU=8; // equal + public static final int LET=9; // let + public static final int ID=10;// // identifier + public static final int END=11; // exit +} \ No newline at end of file -- cgit v1.2.3