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