package net.sf.jlinkgrammar; import java.io.BufferedReader; import java.io.IOException; import java.io.Reader; /** * TODO add javadoc * */ public class PPLexTable { /** array of labels (null-terminated) */ public String labels[] = new String[GlobalBean.PP_LEXER_MAX_LABELS]; /** str. for each label */ public PPLabelNode nodes_of_label[] = new PPLabelNode[GlobalBean.PP_LEXER_MAX_LABELS]; /** efficiency */ public PPLabelNode last_node_of_label[] = new PPLabelNode[GlobalBean.PP_LEXER_MAX_LABELS]; /** state: current node of label */ public PPLabelNode current_node_of_active_label; /** read state: current label */ public int idx_of_active_label; private int yylineno; PPLexTable() { for (int i = 0; i < GlobalBean.PP_LEXER_MAX_LABELS; i++) { nodes_of_label[i] = null; last_node_of_label[i] = null; labels[i] = null; } } /** * post processor set lexer state to first node of this label * @param label * @return false if get_index_of_label returns -1 */ public boolean pp_lexer_set_label(String label) { idx_of_active_label = get_index_of_label(label); if (idx_of_active_label == -1) return false; /* label not found */ current_node_of_active_label = nodes_of_label[idx_of_active_label]; return true; } private int get_index_of_label(String label) { int i; for (i = 0; labels[i] != null; i++) if (labels[i].equals(label)) return i; return -1; } /** * counts all tokens, even the commas */ public int pp_lexer_count_tokens_of_label() { int n; PPLabelNode p; if (idx_of_active_label == -1) throw new RuntimeException("pp_lexer: current label is invalid"); for (n = 0, p = nodes_of_label[idx_of_active_label]; p != null; p = p.next, n++); return n; } /** * retrieves next token of set label, or null if list exhausted */ public String pp_lexer_get_next_token_of_label() { String p; if (current_node_of_active_label == null) return null; p = current_node_of_active_label.str; current_node_of_active_label = current_node_of_active_label.next; return p; } /** * * @param label */ public void set_label(String label) { int i; /* have we seen this label already? If so, abort */ for (i = 0; labels[i] != null && !labels[i].equals(label); i++); if (labels[i] != null) throw new RuntimeException("pp_lexer: label " + label + " multiply defined!"); /* new label. Store it */ if (i == GlobalBean.PP_LEXER_MAX_LABELS - 1) throw new RuntimeException("pp_lexer: too many labels. Raise PP_LEXER_MAX_LABELS"); labels[i] = label; idx_of_active_label = i; } /** * add the single string str to the set of strings associated with label */ public void add_string_to_label(String str) { PPLabelNode new_node; if (idx_of_active_label == -1) throw new RuntimeException("pp_lexer: invalid syntax (line " + yylineno + ")"); if (str.length() > 0 && str.charAt(0) == '@') { add_set_of_strings_to_label(str.substring(1)); return; } /* make sure string is legal */ check_string(str); /* create a new node in (as yet to be determined) linked list of strings */ new_node = new PPLabelNode(); new_node.str = str; new_node.next = null; /* stick newly-created node at the *end* of the appropriate linked list */ if (last_node_of_label[idx_of_active_label] == null) { /* first entry on linked list */ nodes_of_label[idx_of_active_label] = new_node; last_node_of_label[idx_of_active_label] = new_node; } else { /* non-first entry on linked list */ last_node_of_label[idx_of_active_label].next = new_node; last_node_of_label[idx_of_active_label] = new_node; } } /** * add the set of strings, defined earlier by label_of_set, to the set of * strings associated with the current label */ public void add_set_of_strings_to_label(String label_of_set) { PPLabelNode p; int idx_of_label_of_set; if (idx_of_active_label == -1) throw new RuntimeException("pp_lexer: invalid syntax (line " + yylineno + ")"); if ((idx_of_label_of_set = get_index_of_label(label_of_set)) == -1) throw new RuntimeException( "pp_lexer: label " + label_of_set + " must be defined before it's referred to (line " + yylineno + ")"); for (p = nodes_of_label[idx_of_label_of_set]; p != null; p = p.next) add_string_to_label(p.str); } static void check_string(String str) { if (str.length() > 1 && str.indexOf(',') >= 0) throw new RuntimeException("pp_lexer: string " + str + " contains a comma, which is a no-no."); } /** * all tokens until next comma, null-terminated */ public String[] pp_lexer_get_next_group_of_tokens_of_label() { int n; String tokens[]; PPLabelNode p; p = current_node_of_active_label; for (n = 0; p != null && !p.str.equals(","); n++, p = p.next); tokens = new String[n]; p = current_node_of_active_label; for (n = 0; p != null && !p.str.equals(","); n++, p = p.next) tokens[n] = p.str; /* advance "current node of label" state */ current_node_of_active_label = p; if (p != null) current_node_of_active_label = p.next; return tokens; } /** */ public int pp_lexer_count_commas_of_label() { int n; PPLabelNode p; if (idx_of_active_label == -1) throw new RuntimeException("pp_lexer: current label is invalid"); for (n = 0, p = nodes_of_label[idx_of_active_label]; p != null; p = p.next) if (p.str.equals(",")) n++; return n; } /** * Reads a knowledge object into a table for use by other methods. * Called by PPKnowledge. * @param ppknowledge * @param f * @throws java.io.IOException */ public void yylex(PPKnowledge ppknowledge, Reader f) throws IOException { BufferedReader r = new BufferedReader(f); String line = r.readLine(); yylineno = 0; StringBuffer token = new StringBuffer(); while (line != null) { int i = 0; boolean quoteMode = false; while (i < line.length()) { if (quoteMode) { if (line.charAt(i) == '"') { quoteMode = false; add_string_to_label(token.toString()); token.setLength(0); } else { token.append(line.charAt(i)); } } else { if (line.charAt(i) == ';') { if (token.length() > 0) { add_string_to_label(token.toString()); token.setLength(0); } break; } else if (line.charAt(i) == ':') { set_label(token.toString()); token.setLength(0); } else if (line.charAt(i) == ',') { if (token.length() > 0) { add_string_to_label(token.toString()); token.setLength(0); } add_string_to_label(token.toString()); } else if (line.charAt(i) == '"') { if (token.length() > 0) { add_string_to_label(token.toString()); token.setLength(0); } quoteMode = true; } else if (line.charAt(i) == ' ' || line.charAt(i) == '\t') { if (token.length() > 0) { add_string_to_label(token.toString()); token.setLength(0); } } else { token.append(line.charAt(i)); } } i++; } if (quoteMode) { throw new RuntimeException("post_process: open string at line " + yylineno); } if (token.length() > 0) { add_string_to_label(token.toString()); token.setLength(0); } line = r.readLine(); yylineno++; } } }