📄 consumer.java
字号:
for (int i = 0; i < this.rule.rightSize(); i++) if (this.rule.getRightSymbol(i).equals(rule.getRightSymbol(i + 1)) == false) return false; return true; } // consume methods /** Passes the factory for Strategy objects to all contained ConsumerAlternatives. */ public void setStrategyFactoryMethod(StrategyFactoryMethod strategyFactoryMethod) { for (int i = 0; i < sequence.size(); i++) { Object c = sequence.get(i); if (c instanceof Consumer) { ((Consumer) c).setStrategyFactoryMethod(strategyFactoryMethod); } } } /** Reads from input. Returns null if input did not match, else a result tree containing the text. Ensures that a nullable consumer never returns null and a repeatable consumer repeats. @param input Input object where to read from. @return null if no match, else scanned input as a result tree. */ public ResultTree consume(InputText input) throws IOException { // prepare scanning for results ResultTree result = isRepeatable() ? ensureResultTree(null) : null; // prepare a list container when repeatable ResultTree r; Token.Address start = new Token.Address(input.getScanLine(), input.getScanColumn(), input.getScanOffset()); // consume input and optionally loop when having a repeatable rule do { r = consumeInternal(input); if (r != null && r.hasText()) result = (result == null) ? r : result.addChild(r); } while (r != null && isRepeatable()); // check the result tree element if (result != null && isRepeatable() && result.getChildCount() <= 0) result = null; if (result == null && isNullable()) // having read no input should not break loop of caller result = ensureResultTree(null); // return empty result element // add range when there was a result if (result != null) { Token.Address end = new Token.Address(input.getScanLine(), input.getScanColumn(), input.getScanOffset()); result.setRange(new Token.Range(start, end)); } return result; } /** Consumes characters from Input and stores it into returned result tree. Returns null if nothing has been consumed. */ protected ResultTree consumeInternal(InputText input) throws IOException { ResultTree result = null; boolean ok = true; int mark = input.getMark(); Token.Address start = new Token.Address(input.getScanLine(), input.getScanColumn(), input.getScanOffset()); // all members of this sequence must match for (int i = 0; ok && i < sequence.size(); i++) { // first check constraint consumers negatively for (int j = 0; ok && constraints != null && j < constraints.size(); j++) { Consumer cc = (Consumer) constraints.get(j); int mark1 = input.getMark(); // set mark as constraint-consumer is no permitted consumer ok = (cc.consumeInternal(input) == null); // ok when constraint failed to read input.setMark(mark1); // reset to mark } if (ok) { // no constraint succeeded, now check positively Object o = sequence.get(i); if (o instanceof Consumer) { // match next consumer Consumer cc = (Consumer)o; ResultTree r = cc.consume(input); if (r == null) ok = false; else result = ensureResultTree(result).addChild(r); } else if (o instanceof CharacterSet) { // match character set CharacterSet charSet = (CharacterSet)o; int ic = input.read(); char c = (char)ic; if (ic == Input.EOF || charSet.includes(c) == false) ok = false; else result = ensureResultTree(result).append(c); } else { // match a literal terminal String String s = (String)o; int j = 0; do { int ic = input.read(); ok = (ic != Input.EOF && ((char)ic) == s.charAt(j)); j++; } while (ok && j < s.length()); if (ok) result = ensureResultTree(result).append(s); } // end possible sequence objects } // end if ok (not constrained) } // end for all sequences if (ok && result != null && result.hasText()) { // sequence did match and read non-null text Token.Address end = new Token.Address(input.getScanLine(), input.getScanColumn(), input.getScanOffset()); result.setRange(new Token.Range(start, end)); //System.err.println("Consumer success, free memory: "+Runtime.getRuntime().freeMemory()+", "+rule); return result; // null-text will be considered by consume() that knows about nullable rules } input.setMark(mark); // start again from initial mark //System.err.println("Consumer failed: "+rule); return null; // there was no match } private ResultTree ensureResultTree(ResultTree result) { if (result == null) result = new ResultTree(rule); return result; } /** String representation of consumer: hashcode, sequence and constraints. */ public String toString() { return hashCode()+ "("+getStartVariance()+","+getStartLength()+","+getFixedLength()+")> "+ toStringBase()+ (isNullable() && isRepeatable() ? " *" : isNullable() ? " ?" : isRepeatable() ? " +" : ""); } /** Returns the base string for toString() method. */ protected String toStringBase() { StringBuffer sb = new StringBuffer(); listToString(sequence, sb, " ", false); listToString(constraints, sb, " - ", true); return sb.toString(); } /** Converts a list into String, for toString() method. */ protected void listToString(List list, StringBuffer sb, String separator, boolean separatorAtFirst) { for (int i = 0; list != null && i < list.size(); i++) { Object o = list.get(i); if (separatorAtFirst || i > 0) sb.append(separator); if (o instanceof Consumer) sb.append("["+o.hashCode()+"]"); else // String or CharacterSet sb.append(o.toString()); } } /** Returns true if the passed consumer could be concurrent with this. This method does not consider constraints, as these could be complex. */ public boolean overlaps(Consumer cc) { Object o1 = sequence.get(0); if (o1 instanceof Consumer) { // drill down return ((Consumer)o1).overlaps(cc); } else { // primitive found if (cc.sequence.size() <= 0) // must be ConsumerAlternatives return cc.overlaps(this); Object o2 = cc.sequence.get(0); if (o2 instanceof Consumer) { // drill down return ((Consumer)o2).overlaps(this); } else if (o1 instanceof CharacterSet) { if (o2 instanceof CharacterSet) return ((CharacterSet)o1).overlaps((CharacterSet)o2); else if (o2 instanceof String) return ((CharacterSet)o1).includes(((String)o2).charAt(0)); } else if (o2 instanceof CharacterSet) { if (o1 instanceof String) return ((CharacterSet)o2).includes(((String)o1).charAt(0)); } String seq1 = (String) o1; String seq2 = (String) o2; return seq1.charAt(0) == seq2.charAt(0); } } // helper classes /** Marker class for references that must be resolved after building consumers. */ public static class Reference { String nonterminal; Reference(String nonterminal) { this.nonterminal = nonterminal; } public String toString() { return nonterminal; } } private static class CharacterSet implements Serializable { private String stringRepres; private char firstChar, lastChar; CharacterSet(String first, String last) throws LexerException { this.firstChar = first.charAt(0); this.lastChar = last.charAt(0); if (firstChar >= lastChar) throw new LexerException("First character is bigger equal last: "+toString()); } public char getFirstChar() { return firstChar; } public char getLastChar() { return lastChar; } /** Returns the number of contained characters. */ public int getVariance() { return lastChar - firstChar; } /** Returns true if passed character is contained in this set. */ public boolean includes(char c) { return c >= firstChar && c <= lastChar; } /** Returns true if passed character set contains characters contained in this set. */ public boolean overlaps(CharacterSet other) { return other.includes(firstChar) || other.includes(lastChar) || includes(other.firstChar) || includes(other.lastChar); } public String toString() { if (stringRepres == null) { if (Character.isISOControl(firstChar) || Character.isISOControl(lastChar)) this.stringRepres = Integer.toHexString(firstChar)+".."+Integer.toHexString(lastChar); else this.stringRepres = firstChar+".."+lastChar; } return stringRepres; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -