001: package ro.infoiasi.donald.compiler.lexer;
002:
003: import ro.infoiasi.donald.compiler.lexer.exceptions.*;
004: import java.util.*;
005:
006: public class ExpList extends ArrayList {
007: private Alphabet alpha = new Alphabet();
008:
009: public ExpList() {
010: super ();
011: }
012:
013: public ExpList(String s) throws ExpParseError {
014: super ();
015:
016: Stack stackPar = new Stack();
017:
018: for (int i = 0; i < s.length(); i++) {
019: char ch = s.charAt(i);
020: switch (ch) {
021: case '(':
022: addParenthesisLeft(i, stackPar);
023: break;
024: case ')':
025: addParenthesisRight(i, stackPar);
026: break;
027: case '\\':
028: i = escapeNext(i, s);
029: break;
030: default: {
031: Operator op = Operator.get(ch);
032: if (op != null) {
033: addOperatorToken(i, op);
034: } else {
035: addSymbolToken(i, ch);
036: }
037: }
038: break;
039: }
040: }
041: if (stackPar.size() != 0) {
042: throw new ExpParseError("Parenthesis is not closing",
043: ((ParenthesisLeft) stackPar.peek()).strIndex());
044: }
045: }
046:
047: public ExpToken lastToken() {
048: return (ExpToken) get(size() - 1);
049: }
050:
051: public void addToken(ExpToken et) {
052: Class ce = et.getClass();
053: if (ce == SymbolToken.class
054: || ce == ParenthesisLeft.class
055: || (ce == OperatorToken.class && ((OperatorToken) et)
056: .operator().isUnaryRight())) {
057: /* Implicit concatenation: If the current tooken is
058: a symbol or a open paranthesis or an unary-right operator
059: and is preceded by
060: a symbol or a closing paranthesis or an unary-left operator
061: then insert Operator.CONCAT */
062: if (size() > 0) {
063: Class cl = lastToken().getClass();
064: if (cl == SymbolToken.class
065: || cl == ParenthesisRight.class
066: || (cl == OperatorToken.class && ((OperatorToken) lastToken())
067: .operator().isUnaryLeft())) {
068: addToken(new OperatorToken(et.strIndex(), size(),
069: Operator.CONCAT));
070: et.incTokenNo();
071: }
072: }
073: }
074: add(et);
075: }
076:
077: public void addParenthesisLeft(int index, Stack stackPar) {
078: ParenthesisLeft parLeft = new ParenthesisLeft(index, size());
079: stackPar.push(parLeft);
080: addToken(parLeft);
081: }
082:
083: public void addParenthesisRight(int index, Stack stackPar)
084: throws ExpParseError {
085: if (stackPar.size() == 0) {
086: throw new ExpParseError("Parenthesis closing too soon",
087: index);
088: }
089: ParenthesisLeft parLeft = (ParenthesisLeft) stackPar.pop();
090: ParenthesisRight parRight = new ParenthesisRight(index, size());
091: parLeft.setPair(parRight);
092: parRight.setPair(parLeft);
093: addToken(parRight);
094: }
095:
096: public void addOperatorToken(int index, Operator op) {
097: addToken(new OperatorToken(index, size(), op));
098: }
099:
100: public void addSymbolToken(int index, char ch) {
101: alpha.addSymbol(ch);
102: SymbolToken symbolToken = new SymbolToken(index, size(), ch);
103: addToken(symbolToken);
104: }
105:
106: public int escapeNext(int index, String s) throws ExpParseError {
107: index++;
108: if (index < s.length()) {
109: char ch = s.charAt(index);
110: switch (ch) {
111: case 'n':
112: addSymbolToken(index, '\n');
113: break;
114: // more cases should be added here
115: default: { // all operators can be escaped
116: Operator op = Operator.get(ch);
117: if (op != null) {
118: addSymbolToken(index, ch);
119: } else {
120: throw new ExpParseError("Illegal escape character",
121: index);
122: }
123: }
124: }
125: return index;
126: } else {
127: throw new ExpParseError("Nothing left to escape", index);
128: }
129: }
130:
131: public Alphabet getAlphabet() {
132: return alpha;
133: }
134:
135: public String toString() {
136: StringBuffer sb = new StringBuffer();
137: Iterator it = listIterator(0);
138: while (it.hasNext()) {
139: sb.append((it.next()).toString());
140: }
141: return new String(sb);
142: }
143: }
|