private static boolean number(Text t, DataType requiredType, List<Object> valueList) { // posNumber // : cardinality // | '0b' BinaryDigits+ [zZ]? // | '0x' HexDigit+ [zZ]? // | '-'? Pint? ( '.' Digit+ ) ('e' Pint) [fF] // | '-'? Pint [zZfF]? // ; final boolean result; assert !t.isEof() : "Should have been checked by caller"; if (binary(t, valueList, requiredType) || hex(t, valueList, requiredType)) { // ?todo I could allow negatives here // ( binary | hex | '0' ) result = true; } else { // ( Int DecPart | Int | DecPart ) ( 'e' Int )? [zZfF]? final int start = t.cursor(); if ((t.consumeInt() && (decPart(t) || true) && (exponent(t) || true)) || (t.consume('-') || true) && decPart(t) && (exponent(t) || true)) { final String string = t.getString(start); final Object value = deriveType(string, requiredType, t, 10); valueList.add(value); result = true; } else { result = false; } } return result; }
private static boolean text(Text t, List<Object> valueList) { final boolean result; final int start = t.cursor(); if (t.consumeString()) { // +/- 1s: drop the quotes final String textValue = unescape(t, start + 1, t.cursor() - 1); valueList.add(textValue); result = true; } else { // ?todo Could easily detect unterminated string and throw here result = false; } return result; }
private static boolean decPart(Text t) { final boolean result; // '.' Digits+ final int save = t.cursor(); if (t.consume('.') && t.consumeAscii(Text.ASCII_0_9)) { result = true; } else { t.setCursor(save); result = false; } return result; }
private static boolean exponent(Text t) { final boolean result; // 'e' Int final int save = t.cursor(); if (t.consume('e') && t.consumeInt()) { result = true; } else { t.setCursor(save); result = false; } return result; }
private static boolean identifier(Text t, List<Object> valueList) { final boolean result; final int start = t.cursor(); if (Identifier.consume(t)) { final String string = t.getString(start); valueList.add(new Identifier(string)); result = true; } else { result = false; } return result; }
private static boolean time(Text t) { final boolean result; // HH ':' mm ( : ss )? // Try for HH:mm... int reset = t.cursor(); if (t.consumeAscii(Text.ASCII_0_9) && t.consume(':') && t.consumeAscii(Text.ASCII_0_9)) { result = true; reset = t.cursor(); // Try for :ss... if (t.consume(':') && t.consumeAscii(Text.ASCII_0_9)) { reset = t.cursor(); } } else { result = false; } t.setCursor(reset); return result; }
private static boolean date(Text t, List<Object> valueList) { final boolean result; final int start = t.cursor(); if (t.consume('@') && date(t)) { final String string = t.getString(start + 1); // Jump the'@' final LocalDate value = DateU.parseStandardDate(string); valueList.add(value); result = true; } else { result = false; } return result; }
/** * There's a bug in this as it requires seconds in the string whereas the time() function does * not. It seems to be in the Java parser. * * @param tb Source to parse. * @return A Temporal or null if none found. */ @Nullable private static Temporal temporal(Text t) { Temporal result; final int save = t.cursor(); t.consume('@'); final int start = save + 1; // yyyy/MM/dd HH:mm:ss try { if (date(t)) { final int save2 = t.cursor(); t.ws(); if (time(t)) { final String string = t.getString(start); result = DateU.parseStandardDatetime(string); } else { t.setCursor(save2); final String string = t.getString(start); result = DateU.parseStandardDate(string); } } else if (time(t)) { final String string = t.getString(start); result = DateU.parseStandardTime(string); } else { result = null; t.setCursor(save); } } catch (final DateTimeParseException e) { result = null; t.setCursor(save); } return result; }
private static List<Object> elementList(Text t, DataType type) { final List<Object> result = new ArrayList<>(); // elementList: ( WS? value ( WS? ',' WS? value )* WS? )? if (t.ws() && value(t, type, result)) { while (true) { final int save = t.cursor(); if (t.ws() && t.consume(',') && t.ws() && value(t, type, result)) { continue; } t.setCursor(save); break; } } return result; }
private static boolean binary(Text t, List<Object> valueList, DataType requiredType) { final boolean result; // '0b' [01]+ [zZfF]? final int save = t.cursor(); if (t.consume("0b") && t.consumeAscii(Text.ASCII_0_1)) { final String string = t.getString(save + 2); final Object value = deriveType(string, requiredType, t, 2); valueList.add(value); result = true; } else { t.setCursor(save); result = false; } return result; }
private static boolean date(Text t) { final boolean result; // yyyy '/' MM '/' dd final int save = t.cursor(); if (t.consumeAscii(Text.ASCII_0_9) && t.consume('/') && t.consumeAscii(Text.ASCII_0_9) && t.consume('/') && t.consumeAscii(Text.ASCII_0_9)) { result = true; } else { result = false; t.setCursor(save); } return result; }
/** * In Oak it is possible to embed a tab character as an ASCII 8 or as a \t but internally we store * this in ASCII. The same goes for newlines and other tables (see the Oak reference). Here we * convert external format to internal format. * * @param source The text to process, may be null. E.g. "Hello\tworld" (with the quotes) * @return Return an internal format string. */ @Nullable public static String textToInternalFormat(@Nullable String source) throws ParsingException { final String result; assert source == null || source.length() >= 2 && source.charAt(0) == '"' && source.charAt(source.length() - 1) == '"'; if (source == null) { result = null; } else { final Text t = new Text(); final char[] ca = source.toCharArray(); final int length = ca.length - 1; // 1 because remove quotes for (int i = 1; i < length; i++) { // 1 because remove quotes final char c = ca[i]; if (c == '\\') { if (i == length - 1) { error("Invalid text " + source + ", escape at end of line"); } else { i++; final char next = ca[i]; if (next == 't') { t.append('\t'); } else if (next == 'n') { t.append('\n'); } else if (next == '"') { t.append('"'); } else if (next == '\\') { t.append('\\'); } else if (next == 'u') { // Unicode, 1-4 hex characters... i++; final Text hex = new Text(); hex.append(source); hex.setCursor(i); final int start = i; if (hex.consumeAscii(Text.ASCII_0_F)) { final int end = start + Math.min(4, hex.cursor() - start); final String string = hex.getString(start, end); final char u = (char) Integer.parseInt(string, 16); t.append(u); i = end - 1; } else { error("Invalid text " + source + ", incorrect unicode"); } } else { error("Invalid text: \\" + next); } } } else { t.append(c); } } result = t.toString(); } return result; }