| -- |
| -- |
| -- In a parser using this template, the following macro may be redefined: |
| -- |
| -- $additional_interfaces |
| -- $ast_class |
| -- |
| -- B E G I N N I N G O F T E M P L A T E btVTCLParserTemplateD |
| -- |
| %Options programming_language=java,margin=4,backtrack |
| %Options table,error_maps,scopes |
| %options prefix=TK_, |
| %options action=("*.java", "/.", "./") |
| %options ParseTable=lpg.lpgjavaruntime.ParseTable |
| |
| -- |
| -- This template requires that the name of the EOF token be set |
| -- to EOF_TOKEN to be consistent with LexerTemplateD and LexerTemplateE |
| -- |
| $EOF |
| EOF_TOKEN |
| $End |
| |
| $ERROR |
| ERROR_TOKEN |
| $End |
| |
| $Define |
| |
| $Header |
| /. |
| // |
| // Rule $rule_number: $rule_text |
| //./ |
| |
| $BeginAction |
| /. $Header |
| case $rule_number: {./ |
| |
| $EndAction |
| /. break; |
| }./ |
| |
| $BeginJava |
| /.$BeginAction |
| $symbol_declarations./ |
| |
| $EndJava /.$EndAction./ |
| |
| $NoAction |
| /. $Header |
| case $rule_number: |
| break;./ |
| |
| $BadAction |
| /. $Header |
| case $rule_number: |
| throw new Error("No action specified for rule " + $rule_number);./ |
| |
| $NullAction |
| /. $Header |
| case $rule_number: |
| setResult(null); |
| break;./ |
| |
| $BeginActions |
| /. |
| public void ruleAction(int ruleNumber) |
| { |
| switch (ruleNumber) |
| {./ |
| |
| $SplitActions |
| /. |
| default: |
| ruleAction$rule_number(ruleNumber); |
| break; |
| } |
| return; |
| } |
| |
| public void ruleAction$rule_number(int ruleNumber) |
| { |
| switch (ruleNumber) |
| {./ |
| |
| $EndActions |
| /. |
| default: |
| break; |
| } |
| return; |
| }./ |
| |
| -- |
| -- Macros that may be needed in a parser using this template |
| -- |
| $additional_interfaces /../ |
| $ast_class /.$ast_type./ |
| |
| -- |
| -- Old deprecated macros that should NEVER be used. |
| -- |
| $setSym1 /. // macro setSym1 is deprecated. Use function setResult |
| getParser().setSym1./ |
| $setResult /. // macro setResult is deprecated. Use function setResult |
| getParser().setSym1./ |
| $getSym /. // macro getSym is deprecated. Use function getRhsSym |
| getParser().getSym./ |
| $getToken /. // macro getToken is deprecated. Use function getRhsTokenIndex |
| getParser().getToken./ |
| $getIToken /. // macro getIToken is deprecated. Use function getRhsIToken |
| super.getIToken./ |
| $getLeftSpan /. // macro getLeftSpan is deprecated. Use function getLeftSpan |
| getParser().getFirstToken./ |
| $getRightSpan /. // macro getRightSpan is deprecated. Use function getRightSpan |
| getParser().getLastToken./ |
| $End |
| |
| $Globals |
| /.import lpg.lpgjavaruntime.*; |
| ./ |
| $End |
| |
| $Headers |
| /. |
| import org.eclipse.viatra2.errors.info.ErrorInformation; |
| import org.eclipse.viatra2.errors.info.Location; |
| import org.eclipse.viatra2.lpgparser.loader.VTCLMessages; |
| import org.eclipse.viatra2.errors.info.ErrorInformation.ErrorKind; |
| import org.eclipse.viatra2.errors.info.ErrorInformation.ErrorSeverity; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import org.eclipse.viatra2.lpgparser.loader.ExplanationGenerator; |
| |
| public class $action_type extends PrsStream implements RuleAction$additional_interfaces { |
| final String PARSER_MARKER = "org.eclipse.viatra2.loaders.vtclparsermarker"; |
| |
| ExplanationGenerator generator = new ExplanationGenerator(this); |
| |
| private java.util.List<ErrorInformation> allErrorInfos = new java.util.ArrayList<ErrorInformation>(); |
| public java.util.List<ErrorInformation> getAllErrorInfos() { |
| return allErrorInfos; |
| } |
| |
| public void clearParseErrorList() { |
| if (allErrorInfos == null) |
| allErrorInfos = new java.util.ArrayList<ErrorInformation>(); |
| else |
| allErrorInfos.clear(); |
| } |
| |
| private static ParseTable prs = new $prs_type(); |
| private BacktrackingParser btParser; |
| |
| public BacktrackingParser getParser() { return btParser; } |
| private void setResult(Object object) { btParser.setSym1(object); } |
| public Object getRhsSym(int i) { return btParser.getSym(i); } |
| |
| public int getRhsTokenIndex(int i) { return btParser.getToken(i); } |
| public IToken getRhsIToken(int i) { return super.getIToken(getRhsTokenIndex(i)); } |
| |
| public int getRhsFirstTokenIndex(int i) { return btParser.getFirstToken(i); } |
| public IToken getRhsFirstIToken(int i) { return super.getIToken(getRhsFirstTokenIndex(i)); } |
| |
| public int getRhsLastTokenIndex(int i) { return btParser.getLastToken(i); } |
| public IToken getRhsLastIToken(int i) { return super.getIToken(getRhsLastTokenIndex(i)); } |
| |
| public int getLeftSpan() { return btParser.getFirstToken(); } |
| public IToken getLeftIToken() { return super.getIToken(getLeftSpan()); } |
| |
| public int getRightSpan() { return btParser.getLastToken(); } |
| public IToken getRightIToken() { return super.getIToken(getRightSpan()); } |
| |
| public int getRhsErrorTokenIndex(int i) { |
| int index = btParser.getToken(i); |
| IToken err = super.getIToken(index); |
| return (err instanceof ErrorToken ? index : 0); |
| } |
| public ErrorToken getRhsErrorIToken(int i) { |
| int index = btParser.getToken(i); |
| IToken err = super.getIToken(index); |
| return (ErrorToken) (err instanceof ErrorToken ? err : null); |
| } |
| |
| public $action_type(LexStream lexStream) { |
| super(lexStream); |
| |
| try { |
| super.remapTerminalSymbols(orderedTerminalSymbols(), $prs_type.EOFT_SYMBOL); |
| } catch(NullExportedSymbolsException e) { |
| } catch(NullTerminalSymbolsException e) { |
| } catch(UnimplementedTerminalsException e) { |
| java.util.ArrayList unimplemented_symbols = e.getSymbols(); |
| System.out.println("The Lexer will not scan the following token(s):"); |
| for (int i = 0; i < unimplemented_symbols.size(); i++) { |
| Integer id = (Integer) unimplemented_symbols.get(i); |
| System.out.println(" " + $sym_type.orderedTerminalSymbols[id.intValue()]); |
| } |
| System.out.println(); |
| } |
| catch(UndefinedEofSymbolException e) { |
| throw new Error(new UndefinedEofSymbolException |
| ("The Lexer does not implement the Eof symbol " + |
| $sym_type.orderedTerminalSymbols[$prs_type.EOFT_SYMBOL])); |
| } |
| } |
| |
| public String[] orderedTerminalSymbols() { return $sym_type.orderedTerminalSymbols; } |
| public String getTokenKindName(int kind) { return $sym_type.orderedTerminalSymbols[kind]; } |
| public int getEOFTokenKind() { return $prs_type.EOFT_SYMBOL; } |
| public PrsStream getParseStream() { return this; } |
| |
| |
| /** |
| * Called when encountering a single bad character. Do not report |
| * this error at this point. |
| */ |
| public void reportError(int left_char, int right_char) { |
| // System.out.println("reportError(int, int)"); |
| } |
| |
| /** |
| * Reports the parse error by setting the error to <code>errorString</code> |
| * |
| * @param errorCode the error code |
| * @param locationInfo |
| * @param leftToken the token to the left of the error |
| * @param rightToken the token to the right of the error |
| * @param tokenText the text of the bad token |
| */ |
| public void reportError(int errorCode, String locationInfo, int leftToken, int rightToken, String tokenText) { |
| |
| int leftTokenLoc = (leftToken > rightToken ? rightToken : leftToken); |
| int rightTokenLoc = rightToken; |
| String errorString; |
| |
| if (getLine(leftTokenLoc) <= 0) { |
| errorString = VTCLMessages.InvalidVTCL_ERROR_; |
| allErrorInfos.add(new ErrorInformation(errorString, PARSER_MARKER, ErrorKind.PARSE_ERROR)); |
| } |
| else { |
| Location location = new Location( |
| getLine(leftTokenLoc), |
| getColumn(leftTokenLoc), |
| getEndLine(rightTokenLoc), |
| getEndColumn(rightTokenLoc) + 1, |
| getStartOffset(leftTokenLoc), |
| getEndOffset(rightTokenLoc)); |
| |
| switch (errorCode) { |
| case EOF_CODE: |
| case MISPLACED_CODE: |
| case DELETION_CODE: |
| errorString = " Syntax error: " + errorMsgText[errorCode] + " " + |
| '"' + computeInputString( |
| getIToken(leftToken).getStartOffset(), |
| getIToken(rightToken).getEndOffset()) + '"'; |
| break; |
| case INVALID_TOKEN_CODE: |
| errorString = " Syntax error: Token" + " " + |
| '"' + computeInputString( |
| getIToken(leftToken).getStartOffset(), |
| getIToken(rightToken).getEndOffset()) + '"' |
| + " " + errorMsgText[errorCode] + "."; |
| String explanation = generator.calculateErrorExplanation(tokenText, leftToken, rightToken); |
| if (explanation != "") { |
| errorString = errorString + " Cause: " + explanation + "."; |
| } |
| break; |
| |
| case MERGE_CODE: |
| case BEFORE_CODE: |
| case INSERTION_CODE: |
| case SCOPE_CODE: |
| case SUBSTITUTION_CODE: // includes SECONDARY_CODE |
| errorString = " Syntax error: " + tokenText + " " + errorMsgText[errorCode] + " " + |
| '"' + computeInputString( |
| getIToken(leftToken).getStartOffset(), |
| getIToken(rightToken).getEndOffset()) + '"'; |
| break; |
| |
| default: |
| errorString = " Syntax error: " + errorMsgText[errorCode] + " at token " + tokenText; |
| break; |
| } |
| allErrorInfos.add(new |
| ErrorInformation(errorString, |
| PARSER_MARKER, |
| ErrorKind.PARSE_ERROR, |
| location, |
| ErrorSeverity.ERROR)); |
| } |
| |
| } |
| |
| |
| /** |
| * Returns a single line string representation of the input chars |
| * for the given range. |
| * |
| * @param left left most char index |
| * @param right right most char index |
| * @return a single line string representation of the input chars |
| */ |
| private String computeInputString(int left, int right) { |
| StringBuffer result = new StringBuffer(right - left + 1); |
| char[] chars = getInputChars(); |
| |
| for (int i = left; i <= right; i++) { |
| if (chars[i] == '\t') { |
| result.append(' '); |
| } else if (chars[i] == '\n' || chars[i] == '\r' || chars[i] == '\f') { |
| if (i > 0) { |
| if (!Character.isWhitespace(chars[i-1])) { |
| result.append(' '); |
| } |
| } |
| } else { |
| result.append(chars[i]); |
| } |
| |
| } |
| return result.toString(); |
| } |
| |
| |
| |
| /** |
| * Report error message for given error_token by calling |
| * method <code>reportError/5</code> is called finally |
| * @param error_token |
| * @param msg |
| */ |
| public final void reportErrorTokenMessage(int error_token, String msg) |
| { |
| allErrorInfos.add(new |
| ErrorInformation(msg, |
| PARSER_MARKER, |
| ErrorKind.PARSE_ERROR, |
| getLine(error_token), |
| getColumn(error_token), |
| getEndLine(error_token), |
| getEndColumn(error_token))); |
| } |
| |
| /** |
| * This SymbolTable class is from the IMP project |
| */ |
| public static class SymbolTable { |
| private Map<String,ASTNode> table = new HashMap<String,ASTNode>(); |
| |
| public void addDefinition(String name, ASTNode def) { table.put(name, def); } |
| public ASTNode lookup(String name) { return table.get(name); } |
| public List<String> allSymbolsOfType(Class type) { |
| List<String> result= new ArrayList<String>(); |
| |
| for(String sym: table.keySet()) { |
| ASTNode def= table.get(sym); |
| |
| if (type.isInstance(def)) |
| result.add(sym); |
| } |
| return result; |
| } |
| public <T> List<T> allDefsOfType(Class<T> type) { |
| List<T> result = new ArrayList<T>(); |
| |
| for(String sym: table.keySet()) { |
| ASTNode def= table.get(sym); |
| |
| if (type.isInstance(def)) |
| result.add((T) def); |
| } |
| return result; |
| } |
| public Set<String> allSymbols() { return table.keySet(); } |
| } |
| // protected static SymbolTable symtab; |
| // { symtab = new SymbolTable(); } |
| |
| public $ast_class parser() |
| { |
| return parser(null, 0); |
| } |
| |
| public $ast_class parser(Monitor monitor) |
| { |
| return parser(monitor, 0); |
| } |
| |
| public $ast_class parser(int error_repair_count) |
| { |
| return parser(null, error_repair_count); |
| } |
| |
| public $ast_class parser(Monitor monitor, int error_repair_count) |
| { |
| try |
| { |
| btParser = new BacktrackingParser(monitor, this, prs, this); |
| } |
| catch (NotBacktrackParseTableException e) |
| { |
| throw new Error(new NotBacktrackParseTableException |
| ("Regenerate $prs_type.java with -BACKTRACK option")); |
| } |
| catch (BadParseSymFileException e) |
| { |
| throw new Error(new BadParseSymFileException("Bad Parser Symbol File -- $sym_type.java")); |
| } |
| |
| try |
| { |
| return ($ast_class) btParser.parse(error_repair_count); |
| } |
| catch (BadParseException e) |
| { |
| reset(e.error_token); // point to error token |
| DiagnoseParser diagnoseParser = new DiagnoseParser(this, prs); |
| diagnoseParser.diagnose(e.error_token); |
| } |
| |
| return null; |
| } |
| |
| ./ |
| |
| $End |
| |
| $Rules |
| /.$BeginActions./ |
| $End |
| |
| $Trailers |
| /. |
| $EndActions |
| } |
| ./ |
| $End |
| |
| -- |
| -- E N D O F T E M P L A T E |
| -- |