package edu.stanford.nlp.sempre; import java.util.Arrays; /** * SimpleAnalyzer takes an utterance and applies simple methods to pre-process * * @author akchou */ public class SimpleAnalyzer extends LanguageAnalyzer { // Stanford tokenizer doesn't break hyphens. // Replace hypens with spaces for utterances like // "Spanish-speaking countries" but not for "2012-03-28". public static String breakHyphens(String utterance) { StringBuilder buf = new StringBuilder(utterance); for (int i = 0; i < buf.length(); i++) { if (buf.charAt(i) == '-' && (i + 1 < buf.length() && Character.isLetter(buf.charAt(i + 1)))) buf.setCharAt(i, ' '); } return buf.toString(); } private static final String[] numbers = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"}; public LanguageInfo analyze(String utterance) { LanguageInfo languageInfo = new LanguageInfo(); // Clear these so that analyze can hypothetically be called // multiple times. languageInfo.tokens.clear(); languageInfo.posTags.clear(); languageInfo.nerTags.clear(); languageInfo.nerValues.clear(); languageInfo.lemmaTokens.clear(); // Break hyphens utterance = breakHyphens(utterance); // Default analysis - create tokens crudely StringBuilder buf = new StringBuilder(); for (int i = 0; i < utterance.length(); i++) { char c = utterance.charAt(i); // Put whitespace around certain characters. // TODO(pliang): handle contractions such as "can't" properly. boolean boundaryBefore = !(i - 1 >= 0) || utterance.charAt(i - 1) == ' '; boolean boundaryAfter = !(i + 1 < utterance.length()) || utterance.charAt(i + 1) == ' '; boolean separate; if (c == '.') // Break off period if already space around it (to preserve numbers like 3.5) separate = boundaryBefore || boundaryAfter; else separate = (",?'\"[]".indexOf(c) != -1); if (separate) buf.append(' '); // Convert quotes if (c == '"') buf.append(boundaryBefore ? "``" : "''"); else if (c == '\'') buf.append(boundaryBefore ? "`" : "'"); else buf.append(c); if (separate) buf.append(' '); } utterance = buf.toString().trim(); if (!utterance.equals("")) { String[] tokens = utterance.split("\\s+"); for (String token : tokens) { languageInfo.tokens.add(LanguageAnalyzer.opts.lowerCaseTokens ? token.toLowerCase() : token); String lemma = token; if (token.endsWith("s") && token.length() > 1) lemma = token.substring(0, token.length() - 1); languageInfo.lemmaTokens.add(LanguageAnalyzer.opts.lowerCaseTokens ? lemma.toLowerCase() : lemma); // Is it a written out number? int x = Arrays.asList(numbers).indexOf(token); if (x != -1) { languageInfo.posTags.add("CD"); languageInfo.nerTags.add("NUMBER"); languageInfo.nerValues.add(x + ""); continue; } try { Double.parseDouble(token); languageInfo.posTags.add("CD"); languageInfo.nerTags.add("NUMBER"); languageInfo.nerValues.add(token); } catch (NumberFormatException e) { // Guess that capitalized nouns are proper if (Character.isUpperCase(token.charAt(0))) languageInfo.posTags.add("NNP"); else if (token.equals("'") || token.equals("\"") || token.equals("''") || token.equals("``")) languageInfo.posTags.add("''"); else languageInfo.posTags.add("UNK"); languageInfo.nerTags.add("UNK"); languageInfo.nerValues.add("UNK"); } } } return languageInfo; } }