001: /*
002: * Copyright 2004-2008 H2 Group. Licensed under the H2 License, Version 1.0
003: * (http://h2database.com/html/license.html).
004: * Initial Developer: H2 Group
005: */
006: package org.h2.bnf;
007:
008: import java.util.ArrayList;
009: import java.util.HashMap;
010:
011: /**
012: * Represents a sequence of BNF rules, or a list of alternative rules.
013: */
014: public class RuleList implements Rule {
015:
016: private boolean or;
017: private ArrayList list;
018: private boolean mapSet;
019:
020: RuleList(Rule first, Rule next, boolean or) {
021: list = new ArrayList();
022: if (first instanceof RuleList && ((RuleList) first).or == or) {
023: list.addAll(((RuleList) first).list);
024: } else {
025: list.add(first);
026: }
027: if (next instanceof RuleList && ((RuleList) next).or == or) {
028: list.addAll(((RuleList) next).list);
029: } else {
030: list.add(next);
031: }
032: if (!or && Bnf.COMBINE_KEYWORDS) {
033: for (int i = 0; i < list.size() - 1; i++) {
034: Rule r1 = (Rule) list.get(i);
035: Rule r2 = (Rule) list.get(i + 1);
036: if (!(r1 instanceof RuleElement)
037: || !(r2 instanceof RuleElement)) {
038: continue;
039: }
040: RuleElement re1 = (RuleElement) r1;
041: RuleElement re2 = (RuleElement) r2;
042: if (!re1.isKeyword() || !re2.isKeyword()) {
043: continue;
044: }
045: re1 = re1.merge(re2);
046: list.set(i, re1);
047: list.remove(i + 1);
048: i--;
049: }
050: }
051: this .or = or;
052: }
053:
054: public String random(Bnf config, int level) {
055: if (or) {
056: if (level > 10) {
057: if (level > 1000) {
058: // better than stack overflow
059: throw new Error();
060: }
061: return get(0).random(config, level);
062: }
063: int idx = config.getRandom().nextInt(list.size());
064: return get(idx).random(config, level + 1);
065: } else {
066: StringBuffer buff = new StringBuffer();
067: for (int i = 0; i < list.size(); i++) {
068: buff.append(get(i).random(config, level + 1));
069: }
070: return buff.toString();
071: }
072: }
073:
074: private Rule get(int idx) {
075: return ((Rule) list.get(idx));
076: }
077:
078: public String name() {
079: return null;
080: }
081:
082: public Rule last() {
083: return get(list.size() - 1);
084: }
085:
086: public void setLinks(HashMap ruleMap) {
087: if (!mapSet) {
088: for (int i = 0; i < list.size(); i++) {
089: get(i).setLinks(ruleMap);
090: }
091: mapSet = true;
092: }
093: }
094:
095: public String matchRemove(String query, Sentence sentence) {
096: if (query.length() == 0) {
097: return null;
098: }
099: if (or) {
100: for (int i = 0; i < list.size(); i++) {
101: String s = get(i).matchRemove(query, sentence);
102: if (s != null) {
103: return s;
104: }
105: }
106: return null;
107: } else {
108: for (int i = 0; i < list.size(); i++) {
109: Rule r = get(i);
110: query = r.matchRemove(query, sentence);
111: if (query == null) {
112: return null;
113: }
114: }
115: return query;
116: }
117: }
118:
119: public void addNextTokenList(String query, Sentence sentence) {
120: if (sentence.stop()) {
121: //
122: }
123: if (or) {
124: for (int i = 0; i < list.size(); i++) {
125: get(i).addNextTokenList(query, sentence);
126: }
127: } else {
128: for (int i = 0; i < list.size(); i++) {
129: Rule r = get(i);
130: r.addNextTokenList(query, sentence);
131: query = r.matchRemove(query, sentence);
132: if (query == null) {
133: break;
134: }
135: }
136: }
137: }
138:
139: }
|