1 /* 2 * Copyright (c) 2002-2020, the original author or authors. 3 * 4 * This software is distributable under the BSD license. See the terms of the 5 * BSD license in the documentation provided with this software. 6 * 7 * https://opensource.org/licenses/BSD-3-Clause 8 */ 9 package jdk.internal.org.jline.reader; 10 11 import java.util.regex.Matcher; 12 import java.util.regex.Pattern; 13 14 public interface Parser { 15 static final String REGEX_VARIABLE = "[a-zA-Z_]{1,}[a-zA-Z0-9_-]*"; 16 static final String REGEX_COMMAND = "[:]{0,1}[a-zA-Z]{1,}[a-zA-Z0-9_-]*"; 17 parse(String line, int cursor, ParseContext context)18 ParsedLine parse(String line, int cursor, ParseContext context) throws SyntaxError; 19 parse(String line, int cursor)20 default ParsedLine parse(String line, int cursor) throws SyntaxError { 21 return parse(line, cursor, ParseContext.UNSPECIFIED); 22 } 23 isEscapeChar(char ch)24 default boolean isEscapeChar(char ch) { 25 return ch == '\\'; 26 } 27 validCommandName(String name)28 default boolean validCommandName(String name) { 29 return name != null && name.matches(REGEX_COMMAND); 30 } 31 validVariableName(String name)32 default boolean validVariableName(String name) { 33 return name != null && name.matches(REGEX_VARIABLE); 34 } 35 getCommand(final String line)36 default String getCommand(final String line) { 37 String out = ""; 38 Pattern patternCommand = Pattern.compile("^\\s*" + REGEX_VARIABLE + "=(" + REGEX_COMMAND + ")(\\s+.*|$)"); 39 Matcher matcher = patternCommand.matcher(line); 40 if (matcher.find()) { 41 out = matcher.group(1); 42 } else { 43 out = line.trim().split("\\s+")[0]; 44 int idx = out.indexOf("="); 45 if (idx > -1) { 46 out = out.substring(idx + 1); 47 } 48 if (!out.matches(REGEX_COMMAND)) { 49 out = ""; 50 } 51 } 52 return out; 53 } 54 getVariable(final String line)55 default String getVariable(final String line) { 56 String out = null; 57 Pattern patternCommand = Pattern.compile("^\\s*(" + REGEX_VARIABLE + ")\\s*=[^=~].*"); 58 Matcher matcher = patternCommand.matcher(line); 59 if (matcher.find()) { 60 out = matcher.group(1); 61 } 62 return out; 63 } 64 65 enum ParseContext { 66 UNSPECIFIED, 67 68 /** Try a real "final" parse. 69 * May throw EOFError in which case we have incomplete input. 70 */ 71 ACCEPT_LINE, 72 73 /** Parsed words will have all characters present in input line 74 * including quotes and escape chars. 75 * May throw EOFError in which case we have incomplete input. 76 */ 77 SPLIT_LINE, 78 79 /** Parse to find completions (typically after a Tab). 80 * We should tolerate and ignore errors. 81 */ 82 COMPLETE, 83 84 /** Called when we need to update the secondary prompts. 85 * Specifically, when we need the 'missing' field from EOFError, 86 * which is used by a "%M" in a prompt pattern. 87 */ 88 SECONDARY_PROMPT 89 } 90 } 91