merge from master,In preparation for continuing on this experiment branch.

This commit is contained in:
Terence Parr 2012-07-21 10:38:55 -07:00
commit 0141bc058a
116 changed files with 2273 additions and 1712 deletions

View File

@ -1,80 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.antlr</groupId>
<artifactId>antlr4-gunit</artifactId>
<version>4.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>antlr4-gunit</name>
<url>http://www.antlr.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4-runtime</artifactId>
<version>4.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr-runtime</artifactId>
<version>3.4.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>ST4</artifactId>
<version>4.0.4</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src</sourceDirectory>
<resources>
<resource>
<directory>resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.antlr</groupId>
<artifactId>antlr3-maven-plugin</artifactId>
<version>3.4</version>
<configuration>
<sourceDirectory>src</sourceDirectory>
<verbose>true</verbose>
</configuration>
<executions>
<execution>
<goals>
<goal>antlr</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,43 +0,0 @@
group jUnit;
jUnitClass(className, header, options, suites) ::= <<
<header>
import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;
import org.junit.Test;
import org.junit.Before;
import static org.junit.Assert.*;
public class <className> extends org.antlr.v4.gunit.gUnitBase {
@Before public void setup() {
lexerClassName = "<options.lexer>";
parserClassName = "<options.parser>";
<if(options.adaptor)>
adaptorClassName = "<options.adaptor>";
<endif>
}
<suites>
}
>>
header(action) ::= "<action>"
testSuite(name,cases) ::= <<
<cases:{c | <c>}; separator="\n\n"> <! use {...} iterator to get <i> !>
>>
parserRuleTestSuccess(input,expecting) ::= <<
>>
parserRuleTestAST(ruleName,scriptLine,input,expecting) ::= <<
@Test public void test_<name><i>() throws Exception {
// gunit test on line <scriptLine>
RuleReturnScope rstruct = (RuleReturnScope)execParser("<ruleName>", "<input>", <scriptLine>);
Object actual = ((Tree)rstruct.getTree()).toStringTree();
Object expecting = "<expecting>";
assertEquals("testing rule <ruleName>", expecting, actual);
}
>>
string(s) ::= "<s>"

View File

@ -1,46 +0,0 @@
tree grammar ASTVerifier;
options {
ASTLabelType=CommonTree;
tokenVocab = gUnit;
}
@header {
package org.antlr.v4.gunit;
}
gUnitDef
: ^('gunit' ID DOC_COMMENT? (optionsSpec|header)* testsuite+)
;
optionsSpec
: ^(OPTIONS option+)
;
option
: ^('=' ID ID)
| ^('=' ID STRING)
;
header : ^('@header' ACTION);
testsuite
: ^(SUITE ID ID DOC_COMMENT? testcase+)
| ^(SUITE ID DOC_COMMENT? testcase+)
;
testcase
: ^(TEST_OK DOC_COMMENT? input)
| ^(TEST_FAIL DOC_COMMENT? input)
| ^(TEST_RETVAL DOC_COMMENT? input RETVAL)
| ^(TEST_STDOUT DOC_COMMENT? input STRING)
| ^(TEST_STDOUT DOC_COMMENT? input ML_STRING)
| ^(TEST_TREE DOC_COMMENT? input TREE)
| ^(TEST_ACTION DOC_COMMENT? input ACTION)
;
input
: STRING
| ML_STRING
| FILENAME
;

View File

@ -1,155 +0,0 @@
package org.antlr.v4.gunit;
import org.antlr.runtime.ANTLRFileStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RuleReturnScope;
import org.antlr.runtime.tree.BufferedTreeNodeStream;
import org.antlr.runtime.tree.CommonTree;
import org.antlr.runtime.tree.CommonTreeNodeStream;
import org.antlr.stringtemplate.AutoIndentWriter;
import org.antlr.stringtemplate.StringTemplate;
import org.antlr.stringtemplate.StringTemplateGroup;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.List;
public class Gen {
// TODO: don't hardcode
public static final String TEMPLATE_FILE =
"/Users/parrt/antlr/code/antlr4/gunit/resources/org/antlr/v4/gunit/jUnit.stg";
public static void main(String[] args) throws Exception {
if ( args.length==0 ) {help(); System.exit(0);}
String outputDirName = ".";
String fileName = args[0];
if ( args[0].equals("-o") ) {
if ( args.length<3 ) {
help();
System.exit(0);
}
outputDirName = args[1];
fileName = args[2];
}
new Gen().process(fileName, outputDirName);
}
public void process(String fileName, String outputDirName) throws Exception {
// PARSE SCRIPT
ANTLRFileStream fs = new ANTLRFileStream(fileName);
gUnitLexer lexer = new gUnitLexer(fs);
CommonTokenStream tokens = new CommonTokenStream(lexer);
gUnitParser parser = new gUnitParser(tokens);
RuleReturnScope r = parser.gUnitDef();
CommonTree scriptAST = (CommonTree)r.getTree();
System.out.println(scriptAST.toStringTree());
// ANALYZE
CommonTreeNodeStream nodes = new CommonTreeNodeStream(r.getTree());
Semantics sem = new Semantics(nodes);
sem.downup(scriptAST);
System.out.println("options="+sem.options);
// GENERATE CODE
FileReader fr = new FileReader(TEMPLATE_FILE);
StringTemplateGroup templates =
new StringTemplateGroup(fr);
fr.close();
BufferedTreeNodeStream bnodes = new BufferedTreeNodeStream(scriptAST);
jUnitGen gen = new jUnitGen(bnodes);
gen.setTemplateLib(templates);
RuleReturnScope r2 = gen.gUnitDef();
StringTemplate st = (StringTemplate)r2.getTemplate();
st.setAttribute("options", sem.options);
FileWriter fw = new FileWriter(outputDirName+"/"+sem.name+".java");
BufferedWriter bw = new BufferedWriter(fw);
st.write(new AutoIndentWriter(bw));
bw.close();
}
/** Borrowed from Leon Su in gunit v3 */
public static String escapeForJava(String inputString) {
// Gotta escape literal backslash before putting in specials that use escape.
inputString = inputString.replace("\\", "\\\\");
// Then double quotes need escaping (singles are OK of course).
inputString = inputString.replace("\"", "\\\"");
// note: replace newline to String ".\n", replace tab to String ".\t"
inputString = inputString.replace("\n", "\\n").replace("\t", "\\t").replace("\r", "\\r").replace("\b", "\\b").replace("\f", "\\f");
return inputString;
}
public static String normalizeTreeSpec(String t) {
List<String> words = new ArrayList<String>();
int i = 0;
StringBuilder word = new StringBuilder();
while ( i<t.length() ) {
if ( t.charAt(i)=='(' || t.charAt(i)==')' ) {
if ( word.length()>0 ) {
words.add(word.toString());
word.setLength(0);
}
words.add(String.valueOf(t.charAt(i)));
i++;
continue;
}
if ( Character.isWhitespace(t.charAt(i)) ) {
// upon WS, save word
if ( word.length()>0 ) {
words.add(word.toString());
word.setLength(0);
}
i++;
continue;
}
// ... "x" or ...("x"
if ( t.charAt(i)=='"' && (i-1)>=0 &&
(t.charAt(i-1)=='(' || Character.isWhitespace(t.charAt(i-1))) )
{
i++;
while ( i<t.length() && t.charAt(i)!='"' ) {
if ( t.charAt(i)=='\\' &&
(i+1)<t.length() && t.charAt(i+1)=='"' ) // handle \"
{
word.append('"');
i+=2;
continue;
}
word.append(t.charAt(i));
i++;
}
i++; // skip final "
words.add(word.toString());
word.setLength(0);
continue;
}
word.append(t.charAt(i));
i++;
}
if ( word.length()>0 ) {
words.add(word.toString());
}
//System.out.println("words="+words);
StringBuilder buf = new StringBuilder();
for (int j=0; j<words.size(); j++) {
if ( j>0 && !words.get(j).equals(")") &&
!words.get(j-1).equals("(") ) {
buf.append(' ');
}
buf.append(words.get(j));
}
return buf.toString();
}
public static void help() {
System.err.println("org.antlr.v4.gunit.Gen [-o output-dir] gunit-file");
}
}

View File

@ -1,21 +0,0 @@
package org.antlr.v4.gunit;
import org.antlr.runtime.*;
import org.antlr.runtime.tree.BufferedTreeNodeStream;
import org.antlr.runtime.tree.Tree;
public class Interp {
public static void main(String[] args) throws Exception {
String fileName = args[0];
ANTLRFileStream fs = new ANTLRFileStream(fileName);
gUnitLexer lexer = new gUnitLexer(fs);
CommonTokenStream tokens = new CommonTokenStream(lexer);
gUnitParser parser = new gUnitParser(tokens);
RuleReturnScope r = parser.gUnitDef();
System.out.println(((Tree)r.getTree()).toStringTree());
BufferedTreeNodeStream nodes = new BufferedTreeNodeStream(r.getTree());
ASTVerifier verifier = new ASTVerifier(nodes);
verifier.gUnitDef();
}
}

View File

@ -1,36 +0,0 @@
tree grammar Semantics;
options {
filter=true;
ASTLabelType=CommonTree;
tokenVocab = gUnit;
}
@header {
package org.antlr.v4.gunit;
import java.util.Map;
import java.util.HashMap;
}
@members {
public String name;
public Map<String,String> options = new HashMap<String,String>();
}
topdown
: optionsSpec
| gUnitDef
;
gUnitDef
: ^('gunit' ID .*) {name = $ID.text;}
;
optionsSpec
: ^(OPTIONS option+)
;
option
: ^('=' o=ID v=ID) {options.put($o.text, $v.text);}
| ^('=' o=ID v=STRING) {options.put($o.text, $v.text);}
;

View File

@ -1,155 +0,0 @@
grammar gUnit;
options {
output=AST;
ASTLabelType=CommonTree;
}
tokens { SUITE; TEST_OK; TEST_FAIL; TEST_RETVAL; TEST_STDOUT; TEST_TREE; TEST_ACTION; }
@header {
package org.antlr.v4.gunit;
}
@lexer::header {
package org.antlr.v4.gunit;
}
gUnitDef
: DOC_COMMENT? 'gunit' ID ';' (optionsSpec|header)* testsuite+
-> ^('gunit' ID DOC_COMMENT? optionsSpec? header? testsuite+)
;
optionsSpec
: OPTIONS (option ';')+ '}' -> ^(OPTIONS option+)
;
option
: ID '=' optionValue -> ^('=' ID optionValue)
;
optionValue
: ID
| STRING
;
header : '@header' ACTION -> ^('@header' ACTION);
testsuite
: DOC_COMMENT? treeRule=ID 'walks' parserRule=ID ':' testcase+
-> ^(SUITE $treeRule $parserRule DOC_COMMENT? testcase+)
| DOC_COMMENT? ID ':' testcase+ -> ^(SUITE ID DOC_COMMENT? testcase+)
;
testcase
: DOC_COMMENT? input 'OK' -> ^(TEST_OK DOC_COMMENT? input)
| DOC_COMMENT? input 'FAIL' -> ^(TEST_FAIL DOC_COMMENT? input)
| DOC_COMMENT? input 'returns' RETVAL -> ^(TEST_RETVAL DOC_COMMENT? input RETVAL)
| DOC_COMMENT? input '->' STRING -> ^(TEST_STDOUT DOC_COMMENT? input STRING)
| DOC_COMMENT? input '->' ML_STRING -> ^(TEST_STDOUT DOC_COMMENT? input ML_STRING)
| DOC_COMMENT? input '->' TREE -> ^(TEST_TREE DOC_COMMENT? input TREE)
| DOC_COMMENT? input '->' ACTION -> ^(TEST_ACTION DOC_COMMENT? input ACTION)
;
input
: STRING
| ML_STRING
| FILENAME
;
ACTION
: '{' ('\\}'|'\\' ~'}'|~('\\'|'}'))* '}' {setText(getText().substring(1, getText().length()-1));}
;
RETVAL
: NESTED_RETVAL {setText(getText().substring(1, getText().length()-1));}
;
fragment
NESTED_RETVAL :
'['
( options {greedy=false;}
: NESTED_RETVAL
| .
)*
']'
;
TREE : NESTED_AST (' '? NESTED_AST)*;
fragment
NESTED_AST
: '('
( NESTED_AST
| STRING_
| ~('('|')'|'"')
)*
')'
;
OPTIONS : 'options' WS* '{' ;
ID : ID_ ('.' ID_)* ;
fragment
ID_ : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
;
WS : ( ' '
| '\t'
| '\r'
| '\n'
) {$channel=HIDDEN;}
;
SL_COMMENT
: '//' ~('\r'|'\n')* '\r'? '\n' {$channel=HIDDEN;}
;
DOC_COMMENT
: '/**' (options {greedy=false;}:.)* '*/'
;
ML_COMMENT
: '/*' ~'*' (options {greedy=false;}:.)* '*/' {$channel=HIDDEN;}
;
STRING : STRING_ {setText(getText().substring(1, getText().length()-1));} ;
fragment
STRING_
: '"' ('\\"'|'\\' ~'"'|~('\\'|'"'))+ '"'
;
ML_STRING
: '<<' .* '>>' {setText(getText().substring(2, getText().length()-2));}
;
FILENAME
: '/' ID ('/' ID)*
| ID ('/' ID)+
;
/*
fragment
ESC : '\\'
( 'n'
| 'r'
| 't'
| 'b'
| 'f'
| '"'
| '\''
| '\\'
| '>'
| 'u' XDIGIT XDIGIT XDIGIT XDIGIT
| . // unknown, leave as it is
)
;
*/
fragment
XDIGIT :
'0' .. '9'
| 'a' .. 'f'
| 'A' .. 'F'
;

View File

@ -1,49 +0,0 @@
package org.antlr.v4.gunit;
import org.antlr.runtime.*;
import org.antlr.runtime.tree.TreeAdaptor;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class gUnitBase {
public String lexerClassName;
public String parserClassName;
public String adaptorClassName;
public Object execParser(
String ruleName,
String input,
int scriptLine)
throws Exception
{
ANTLRStringStream is = new ANTLRStringStream(input);
Class lexerClass = Class.forName(lexerClassName);
Class[] lexArgTypes = new Class[]{CharStream.class};
Constructor lexConstructor = lexerClass.getConstructor(lexArgTypes);
Object[] lexArgs = new Object[]{is};
TokenSource lexer = (TokenSource)lexConstructor.newInstance(lexArgs);
is.setLine(scriptLine);
CommonTokenStream tokens = new CommonTokenStream(lexer);
Class parserClass = Class.forName(parserClassName);
Class[] parArgTypes = new Class[]{TokenStream.class};
Constructor parConstructor = parserClass.getConstructor(parArgTypes);
Object[] parArgs = new Object[]{tokens};
Parser parser = (Parser)parConstructor.newInstance(parArgs);
// set up customized tree adaptor if necessary
if ( adaptorClassName!=null ) {
parArgTypes = new Class[]{TreeAdaptor.class};
Method m = parserClass.getMethod("setTreeAdaptor", parArgTypes);
Class adaptorClass = Class.forName(adaptorClassName);
m.invoke(parser, adaptorClass.newInstance());
}
Method ruleMethod = parserClass.getMethod(ruleName);
// INVOKE RULE
return ruleMethod.invoke(parser);
}
}

View File

@ -1,53 +0,0 @@
tree grammar jUnitGen;
options {
output=template;
ASTLabelType=CommonTree;
tokenVocab = gUnit;
}
@header {
package org.antlr.v4.gunit;
}
gUnitDef
: ^('gunit' ID DOC_COMMENT? (optionsSpec|header)* suites+=testsuite+)
-> jUnitClass(className={$ID.text}, header={$header.st}, suites={$suites})
;
optionsSpec
: ^(OPTIONS option+)
;
option
: ^('=' ID ID)
| ^('=' ID STRING)
;
header : ^('@header' ACTION) -> header(action={$ACTION.text});
testsuite
: ^(SUITE rule=ID ID DOC_COMMENT? cases+=testcase[$rule.text]+)
| ^(SUITE rule=ID DOC_COMMENT? cases+=testcase[$rule.text]+)
-> testSuite(name={$rule.text}, cases={$cases})
;
testcase[String ruleName]
: ^(TEST_OK DOC_COMMENT? input)
| ^(TEST_FAIL DOC_COMMENT? input)
| ^(TEST_RETVAL DOC_COMMENT? input RETVAL)
| ^(TEST_STDOUT DOC_COMMENT? input STRING)
| ^(TEST_STDOUT DOC_COMMENT? input ML_STRING)
| ^(TEST_TREE DOC_COMMENT? input TREE)
-> parserRuleTestAST(ruleName={$ruleName},
input={$input.st},
expecting={Gen.normalizeTreeSpec($TREE.text)},
scriptLine={$input.start.getLine()})
| ^(TEST_ACTION DOC_COMMENT? input ACTION)
;
input
: STRING -> string(s={Gen.escapeForJava($STRING.text)})
| ML_STRING -> string(s={Gen.escapeForJava($ML_STRING.text)})
| FILENAME
;

View File

@ -36,7 +36,7 @@ import org.antlr.v4.runtime.misc.NotNull;
import org.antlr.v4.runtime.misc.Nullable;
/** How to emit recognition errors */
public interface ANTLRErrorListener<Symbol> {
public interface ANTLRErrorListener {
/** Upon syntax error, notify any interested parties. This is not how to
* recover from errors or compute error messages. The parser
* ANTLRErrorStrategy specifies how to recover from syntax errors
@ -70,12 +70,12 @@ public interface ANTLRErrorListener<Symbol> {
* the parser was able to recover in line without exiting the
* surrounding rule.
*/
public <T extends Symbol> void error(Recognizer<T, ?> recognizer,
@Nullable T offendingSymbol,
int line,
int charPositionInLine,
String msg,
@Nullable RecognitionException e);
public void syntaxError(Recognizer<?, ?> recognizer,
@Nullable Object offendingSymbol,
int line,
int charPositionInLine,
String msg,
@Nullable RecognitionException e);
/** Called when the parser detects a true ambiguity: an input sequence can be matched
* literally by two or more pass through the grammar. ANTLR resolves the ambiguity in

View File

@ -74,28 +74,28 @@ public class ANTLRInputStream implements CharStream {
this(r, INITIAL_BUFFER_SIZE, READ_BUFFER_SIZE);
}
public ANTLRInputStream(Reader r, int size) throws IOException {
this(r, size, READ_BUFFER_SIZE);
public ANTLRInputStream(Reader r, int initialSize) throws IOException {
this(r, initialSize, READ_BUFFER_SIZE);
}
public ANTLRInputStream(Reader r, int size, int readChunkSize) throws IOException {
load(r, size, readChunkSize);
public ANTLRInputStream(Reader r, int initialSize, int readChunkSize) throws IOException {
load(r, initialSize, readChunkSize);
}
public ANTLRInputStream(InputStream input) throws IOException {
this(new InputStreamReader(input), INITIAL_BUFFER_SIZE);
}
public ANTLRInputStream(InputStream input, int size) throws IOException {
this(new InputStreamReader(input), size);
public ANTLRInputStream(InputStream input, int initialSize) throws IOException {
this(new InputStreamReader(input), initialSize);
}
public ANTLRInputStream(InputStream input, int size, int readChunkSize) throws IOException {
this(new InputStreamReader(input), size, readChunkSize);
public ANTLRInputStream(InputStream input, int initialSize, int readChunkSize) throws IOException {
this(new InputStreamReader(input), initialSize, readChunkSize);
}
public void load(Reader r, int size, int readChunkSize)
throws IOException
throws IOException
{
if ( r==null ) {
return;

View File

@ -36,15 +36,14 @@ import org.antlr.v4.runtime.misc.IntervalSet;
*
* @author Sam Harwell
*/
public class BaseErrorListener<Symbol> implements ANTLRErrorListener<Symbol> {
public class BaseErrorListener implements ANTLRErrorListener {
@Override
public <T extends Symbol> void error(Recognizer<T, ?> recognizer,
T offendingSymbol,
int line,
int charPositionInLine,
String msg,
RecognitionException e)
public void syntaxError(Recognizer<?, ?> recognizer,
Object offendingSymbol,
int line,
int charPositionInLine,
String msg,
RecognitionException e)
{
}

View File

@ -239,13 +239,16 @@ public class BufferedTokenStream<T extends Token> implements TokenStream {
return getTokens(start,stop, s);
}
/** Given a starting index, return the index of the next on-channel
* token. Return i if tokens[i] is on channel.
/** Given a starting index, return the index of the next token on channel.
* Return i if tokens[i] is on channel. Return -1 if there are no tokens
* on channel between i and EOF.
*/
protected int nextTokenOnChannel(int i, int channel) {
sync(i);
Token token = tokens.get(i);
while ( token.getType()!=Token.EOF && token.getChannel()!=channel ) {
if ( i>=size() ) return -1;
while ( token.getChannel()!=channel ) {
if ( token.getType()==Token.EOF ) return -1;
i++;
sync(i);
token = tokens.get(i);
@ -253,8 +256,9 @@ public class BufferedTokenStream<T extends Token> implements TokenStream {
return i;
}
/** Given a starting index, return the index of the previous on-channel
* token. Return i if tokens[i] is on channel.
/** Given a starting index, return the index of the previous token on channel.
* Return i if tokens[i] is on channel. Return -1 if there are no tokens
* on channel between i and 0.
*/
protected int previousTokenOnChannel(int i, int channel) {
while ( i>=0 && tokens.get(i).getChannel()!=channel ) {
@ -263,48 +267,75 @@ public class BufferedTokenStream<T extends Token> implements TokenStream {
return i;
}
/** Return a list of all tokens on channel to right of tokenIndex
* until token not on channel found. Current token not considered.
* channel is typically Lexer.DEFAULT_TOKEN_CHANNEL.
/** Collect all tokens on specified channel to the right of
* the current token up until we see a token on DEFAULT_TOKEN_CHANNEL or
* EOF. If channel is -1, find any non default channel token.
*/
public List<T> getOffChannelTokensToRight(int tokenIndex, int channel) {
public List<T> getHiddenTokensToRight(int tokenIndex, int channel) {
if ( p == -1 ) setup();
if ( tokenIndex<0 || tokenIndex>=tokens.size() ) {
throw new IndexOutOfBoundsException(tokenIndex+" not in 0.."+(tokens.size()-1));
}
int nextOnChannel = nextTokenOnChannel(tokenIndex + 1, channel);
int nextOnChannel =
nextTokenOnChannel(tokenIndex + 1, Lexer.DEFAULT_TOKEN_CHANNEL);
int to;
int from = tokenIndex+1;
// if none onchannel to right, nextOnChannel=-1 so set to = last token
if ( nextOnChannel == -1 ) to = size()-1;
else to = nextOnChannel;
if ( nextOnChannel == tokenIndex + 1 ) return null;
// get tokens to right up to next on channel
return tokens.subList(tokenIndex+1, nextOnChannel);
return filterForChannel(from, to, channel);
}
/** Return a list of all tokens on channel to left of tokenIndex
* until token not on channel found. Current token not considered.
* channel is typically Lexer.DEFAULT_TOKEN_CHANNEL.
/** Collect all hidden tokens (any off-default channel) to the right of
* the current token up until we see a token on DEFAULT_TOKEN_CHANNEL
* of EOF.
*/
public List<T> getOffChannelTokensToLeft(int tokenIndex, int channel) {
if ( p == -1 ) setup();
if ( tokenIndex<0 || tokenIndex>=tokens.size() ) {
throw new IndexOutOfBoundsException(tokenIndex+" not in 0.."+(tokens.size()-1));
}
int prevOnChannel = previousTokenOnChannel(tokenIndex - 1, channel);
if ( prevOnChannel == tokenIndex - 1 ) return null;
// get tokens to left up starting at prev on channel + 1 to just before tokenIndex
return tokens.subList(prevOnChannel+1, tokenIndex);
}
public List<T> getHiddenTokensToRight(int tokenIndex) {
return getOffChannelTokensToRight(tokenIndex, Lexer.DEFAULT_TOKEN_CHANNEL);
return getHiddenTokensToRight(tokenIndex, -1);
}
/** Collect all tokens on specified channel to the left of
* the current token up until we see a token on DEFAULT_TOKEN_CHANNEL.
* If channel is -1, find any non default channel token.
*/
public List<T> getHiddenTokensToLeft(int tokenIndex, int channel) {
if ( p == -1 ) setup();
if ( tokenIndex<0 || tokenIndex>=tokens.size() ) {
throw new IndexOutOfBoundsException(tokenIndex+" not in 0.."+(tokens.size()-1));
}
int prevOnChannel =
previousTokenOnChannel(tokenIndex - 1, Lexer.DEFAULT_TOKEN_CHANNEL);
if ( prevOnChannel == tokenIndex - 1 ) return null;
// if none onchannel to left, prevOnChannel=-1 then from=0
int from = prevOnChannel+1;
int to = tokenIndex-1;
return filterForChannel(from, to, channel);
}
/** Collect all hidden tokens (any off-default channel) to the left of
* the current token up until we see a token on DEFAULT_TOKEN_CHANNEL.
*/
public List<T> getHiddenTokensToLeft(int tokenIndex) {
return getOffChannelTokensToLeft(tokenIndex, Lexer.DEFAULT_TOKEN_CHANNEL);
return getHiddenTokensToLeft(tokenIndex, -1);
}
protected List<T> filterForChannel(int from, int to, int channel) {
List<T> hidden = new ArrayList<T>();
for (int i=from; i<=to; i++) {
T t = tokens.get(i);
if ( channel==-1 ) {
if ( t.getChannel()!= Lexer.DEFAULT_TOKEN_CHANNEL ) hidden.add(t);
}
else {
if ( t.getChannel()==channel ) hidden.add(t);
}
}
if ( hidden.size()==0 ) return null;
return hidden;
}
@Override

View File

@ -36,10 +36,11 @@ public interface CharStream extends IntStream {
public static final int MIN_CHAR = Character.MIN_VALUE;
public static final int MAX_CHAR = Character.MAX_VALUE-1; // FFFE is max
/** For unbuffered streams, you can't use this; primarily I'm providing
* a useful interface for action code. Just make sure actions don't
* use this on streams that don't support it.
* @param interval
/** This is primaril a useful interface for action code.
* Just make sure actions don't use this on streams that don't support it.
* For unbuffered streams, you can't use this except in case
* where interval is in current buffer window. Lexer guarantees
* text of current token at emit() time will be available.
*/
public String getText(Interval interval);
}

View File

@ -29,9 +29,24 @@
package org.antlr.v4.runtime;
import org.antlr.v4.runtime.misc.Interval;
public class CommonTokenFactory implements TokenFactory<CommonToken> {
public static final TokenFactory<CommonToken> DEFAULT = new CommonTokenFactory();
/** Copy text for token out of input char stream. Useful when input
* stream is unbuffered.
* @see UnbufferedCharStream
*/
protected final boolean copyText;
/** Create factory and indicate whether or not the factory copy
* text out of the char stream.
*/
public CommonTokenFactory(boolean copyText) { this.copyText = copyText; }
public CommonTokenFactory() { this(false); }
@Override
public CommonToken create(TokenSource source, int type, String text,
int channel, int start, int stop,
@ -43,6 +58,12 @@ public class CommonTokenFactory implements TokenFactory<CommonToken> {
if ( text!=null ) {
t.setText(text);
}
else {
if ( copyText ) {
CharStream input = source.getInputStream();
t.setText(input.getText(Interval.of(start,stop)));
}
}
return t;
}

View File

@ -32,16 +32,16 @@ package org.antlr.v4.runtime;
*
* @author Sam Harwell
*/
public class ConsoleErrorListener extends BaseErrorListener<Object> {
public class ConsoleErrorListener extends BaseErrorListener {
public static final ConsoleErrorListener INSTANCE = new ConsoleErrorListener();
@Override
public <T extends Object> void error(Recognizer<T, ?> recognizer,
T offendingSymbol,
int line,
int charPositionInLine,
String msg,
RecognitionException e)
public void syntaxError(Recognizer<?, ?> recognizer,
Object offendingSymbol,
int line,
int charPositionInLine,
String msg,
RecognitionException e)
{
System.err.println("line " + line + ":" + charPositionInLine + " " + msg);
}

View File

@ -56,7 +56,7 @@ public class DefaultErrorStrategy implements ANTLRErrorStrategy {
/** The index into the input stream where the last error occurred.
* This is used to prevent infinite loops where an error is found
* but no token is consumed during recovery...another error is found,
* ad naseum. This is a failsafe mechanism to guarantee that at least
* ad nauseum. This is a failsafe mechanism to guarantee that at least
* one token/tree node is consumed for two errors.
*/
protected int lastErrorIndex = -1;
@ -126,7 +126,8 @@ public class DefaultErrorStrategy implements ANTLRErrorStrategy {
// lastErrorIndex+
// ", states="+lastErrorStates);
if ( lastErrorIndex==recognizer.getInputStream().index() &&
lastErrorStates.contains(recognizer._ctx.s) ) {
lastErrorStates != null &&
lastErrorStates.contains(recognizer._ctx.s) ) {
// uh oh, another error at same token index and previously-visited
// state in ATN; must be a case where LT(1) is in the recovery
// token set so nothing got consumed. Consume a single token

View File

@ -35,7 +35,7 @@ import org.antlr.v4.runtime.misc.Interval;
import org.antlr.v4.runtime.misc.IntervalSet;
import org.antlr.v4.runtime.misc.NotNull;
public class DiagnosticErrorListener extends BaseErrorListener<Token> {
public class DiagnosticErrorListener extends BaseErrorListener {
@Override
public void reportAmbiguity(@NotNull Parser recognizer,
DFA dfa, int startIndex, int stopIndex, @NotNull IntervalSet ambigAlts,

View File

@ -1,3 +1,31 @@
/*
[The "BSD license"]
Copyright (c) 2012 Terence Parr
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.runtime;
/** This signifies any kind of mismatched input exceptions such as

View File

@ -32,7 +32,9 @@ import org.antlr.v4.runtime.atn.LexerATNSimulator;
import org.antlr.v4.runtime.misc.Interval;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.EmptyStackException;
import java.util.List;
/** A lexer is recognizer that draws input symbols from a character stream.
* lexer grammars result in a subclass of this object. A Lexer object
@ -97,6 +99,8 @@ public abstract class Lexer extends Recognizer<Integer, LexerATNSimulator>
*/
public String _text;
public Lexer() { }
public Lexer(CharStream input) {
this._input = input;
}
@ -126,40 +130,57 @@ public abstract class Lexer extends Recognizer<Integer, LexerATNSimulator>
*/
@Override
public Token nextToken() {
if (_hitEOF) return anEOF();
if (_input == null) {
throw new IllegalStateException("nextToken requires a non-null input stream.");
}
outer:
while (true) {
_token = null;
_channel = Token.DEFAULT_CHANNEL;
_tokenStartCharIndex = _input.index();
_tokenStartCharPositionInLine = getInterpreter().getCharPositionInLine();
_tokenStartLine = getInterpreter().getLine();
_text = null;
do {
_type = Token.INVALID_TYPE;
if (_hitEOF) {
emitEOF();
return _token;
}
// Mark start location in char stream so unbuffered streams are
// guaranteed at least have text of current token
int tokenStartMarker = _input.mark();
try{
outer:
while (true) {
_token = null;
_channel = Token.DEFAULT_CHANNEL;
_tokenStartCharIndex = _input.index();
_tokenStartCharPositionInLine = getInterpreter().getCharPositionInLine();
_tokenStartLine = getInterpreter().getLine();
_text = null;
do {
_type = Token.INVALID_TYPE;
// System.out.println("nextToken line "+tokenStartLine+" at "+((char)input.LA(1))+
// " in mode "+mode+
// " at index "+input.index());
int ttype;
try {
ttype = getInterpreter().match(_input, _mode);
}
catch (LexerNoViableAltException e) {
notifyListeners(e); // report error
recover(e);
ttype = SKIP;
}
if ( _input.LA(1)==CharStream.EOF ) {
_hitEOF = true;
}
if ( _type == Token.INVALID_TYPE ) _type = ttype;
if ( _type ==SKIP ) {
continue outer;
}
} while ( _type ==MORE );
if ( _token ==null ) emit();
return _token;
int ttype;
try {
ttype = getInterpreter().match(_input, _mode);
}
catch (LexerNoViableAltException e) {
notifyListeners(e); // report error
recover(e);
ttype = SKIP;
}
if ( _input.LA(1)==CharStream.EOF ) {
_hitEOF = true;
}
if ( _type == Token.INVALID_TYPE ) _type = ttype;
if ( _type ==SKIP ) {
continue outer;
}
} while ( _type ==MORE );
if ( _token == null ) emit();
return _token;
}
}
finally {
// make sure we release marker after match or
// unbuffered char stream will keep buffering
_input.release(tokenStartMarker);
}
}
@ -219,10 +240,10 @@ public abstract class Lexer extends Recognizer<Integer, LexerATNSimulator>
return _input;
}
/** Currently does not support multiple emits per nextToken invocation
* for efficiency reasons. Subclass and override this method and
* nextToken (to push tokens into a list and pull from that list rather
* than a single variable as this implementation does).
/** By default does not support multiple emits per nextToken invocation
* for efficiency reasons. Subclass and override this method, nextToken,
* and getToken (to push tokens into a list and pull from that list
* rather than a single variable as this implementation does).
*/
public void emit(Token token) {
getInterpreter().traceEmit(token);
@ -243,7 +264,7 @@ public abstract class Lexer extends Recognizer<Integer, LexerATNSimulator>
return t;
}
public Token anEOF() {
public Token emitEOF() {
int cpos = getCharPositionInLine();
// The character position for EOF is one beyond the position of
// the previous token's last character
@ -253,6 +274,7 @@ public abstract class Lexer extends Recognizer<Integer, LexerATNSimulator>
}
Token eof = _factory.create(this, Token.EOF, null, Token.DEFAULT_CHANNEL, _input.index(), _input.index()-1,
getLine(), cpos);
emit(eof);
return eof;
}
@ -303,6 +325,9 @@ public abstract class Lexer extends Recognizer<Integer, LexerATNSimulator>
this._text = text;
}
/** Override if emitting multiple tokens. */
public Token getToken() { return _token; }
public void setToken(Token _token) {
this._token = _token;
}
@ -320,6 +345,19 @@ public abstract class Lexer extends Recognizer<Integer, LexerATNSimulator>
return null;
}
/** Return a list of all Token objects in input char stream.
* Forces load of all tokens. Does not include EOF token.
*/
public List<? extends Token> getAllTokens() {
List<Token> tokens = new ArrayList<Token>();
Token t = nextToken();
while ( t.getType()!=Token.EOF ) {
tokens.add(t);
t = nextToken();
}
return tokens;
}
public void recover(LexerNoViableAltException e) {
getInterpreter().consume(_input); // skip a char and try again
}
@ -328,8 +366,8 @@ public abstract class Lexer extends Recognizer<Integer, LexerATNSimulator>
String msg = "token recognition error at: '"+
_input.getText(Interval.of(_tokenStartCharIndex, _input.index()))+"'";
ANTLRErrorListener<? super Integer> listener = getErrorListenerDispatch();
listener.error(this, null, _tokenStartLine, _tokenStartCharPositionInLine, msg, e);
ANTLRErrorListener listener = getErrorListenerDispatch();
listener.syntaxError(this, null, _tokenStartLine, _tokenStartCharPositionInLine, msg, e);
}
public String getCharErrorDisplay(int c) {

View File

@ -316,8 +316,8 @@ public abstract class Parser extends Recognizer<Token, ParserATNSimulator<Token>
charPositionInLine = ((Token) offendingToken).getCharPositionInLine();
}
ANTLRErrorListener<? super Token> listener = getErrorListenerDispatch();
listener.error(this, offendingToken, line, charPositionInLine, msg, e);
ANTLRErrorListener listener = getErrorListenerDispatch();
listener.syntaxError(this, offendingToken, line, charPositionInLine, msg, e);
}
/** Consume the current symbol and return it. E.g., given the following

View File

@ -38,23 +38,23 @@ import java.util.Collection;
*
* @author Sam Harwell
*/
public class ProxyErrorListener<Symbol> implements ANTLRErrorListener<Symbol> {
private final Collection<? extends ANTLRErrorListener<? super Symbol>> delegates;
public class ProxyErrorListener implements ANTLRErrorListener {
private final Collection<? extends ANTLRErrorListener> delegates;
public ProxyErrorListener(Collection<? extends ANTLRErrorListener<? super Symbol>> delegates) {
public ProxyErrorListener(Collection<? extends ANTLRErrorListener> delegates) {
this.delegates = delegates;
}
@Override
public <T extends Symbol> void error(Recognizer<T, ?> recognizer,
T offendingSymbol,
int line,
int charPositionInLine,
String msg,
RecognitionException e)
public void syntaxError(Recognizer<?, ?> recognizer,
Object offendingSymbol,
int line,
int charPositionInLine,
String msg,
RecognitionException e)
{
for (ANTLRErrorListener<? super Symbol> listener : delegates) {
listener.error(recognizer, offendingSymbol, line, charPositionInLine, msg, e);
for (ANTLRErrorListener listener : delegates) {
listener.syntaxError(recognizer, offendingSymbol, line, charPositionInLine, msg, e);
}
}
@ -66,7 +66,7 @@ public class ProxyErrorListener<Symbol> implements ANTLRErrorListener<Symbol> {
IntervalSet ambigAlts,
ATNConfigSet configs)
{
for (ANTLRErrorListener<? super Symbol> listener : delegates) {
for (ANTLRErrorListener listener : delegates) {
listener.reportAmbiguity(recognizer, dfa, startIndex, stopIndex, ambigAlts, configs);
}
}
@ -78,7 +78,7 @@ public class ProxyErrorListener<Symbol> implements ANTLRErrorListener<Symbol> {
int stopIndex,
ATNConfigSet configs)
{
for (ANTLRErrorListener<? super Symbol> listener : delegates) {
for (ANTLRErrorListener listener : delegates) {
listener.reportAttemptingFullContext(recognizer, dfa, startIndex, stopIndex, configs);
}
}
@ -90,7 +90,7 @@ public class ProxyErrorListener<Symbol> implements ANTLRErrorListener<Symbol> {
int stopIndex,
ATNConfigSet configs)
{
for (ANTLRErrorListener<? super Symbol> listener : delegates) {
for (ANTLRErrorListener listener : delegates) {
listener.reportContextSensitivity(recognizer, dfa, startIndex, stopIndex, configs);
}
}

View File

@ -42,8 +42,10 @@ public abstract class Recognizer<Symbol, ATNInterpreter extends ATNSimulator> {
public static final int EOF=-1;
@NotNull
private List<ANTLRErrorListener<? super Symbol>> _listeners =
new CopyOnWriteArrayList<ANTLRErrorListener<? super Symbol>>() {{ add(ConsoleErrorListener.INSTANCE); }};
private List<ANTLRErrorListener> _listeners =
new CopyOnWriteArrayList<ANTLRErrorListener>() {{
add(ConsoleErrorListener.INSTANCE);
}};
protected ATNInterpreter _interp;
@ -99,7 +101,7 @@ public abstract class Recognizer<Symbol, ATNInterpreter extends ATNSimulator> {
/**
* @throws NullPointerException if {@code listener} is {@code null}.
*/
public void addErrorListener(@NotNull ANTLRErrorListener<? super Symbol> listener) {
public void addErrorListener(@NotNull ANTLRErrorListener listener) {
if (listener == null) {
throw new NullPointerException("listener cannot be null.");
}
@ -107,7 +109,7 @@ public abstract class Recognizer<Symbol, ATNInterpreter extends ATNSimulator> {
_listeners.add(listener);
}
public void removeErrorListener(@NotNull ANTLRErrorListener<? super Symbol> listener) {
public void removeErrorListener(@NotNull ANTLRErrorListener listener) {
_listeners.remove(listener);
}
@ -116,12 +118,12 @@ public abstract class Recognizer<Symbol, ATNInterpreter extends ATNSimulator> {
}
@NotNull
public List<? extends ANTLRErrorListener<? super Symbol>> getErrorListeners() {
return new ArrayList<ANTLRErrorListener<? super Symbol>>(_listeners);
public List<? extends ANTLRErrorListener> getErrorListeners() {
return new ArrayList<ANTLRErrorListener>(_listeners);
}
public ANTLRErrorListener<? super Symbol> getErrorListenerDispatch() {
return new ProxyErrorListener<Symbol>(getErrorListeners());
public ANTLRErrorListener getErrorListenerDispatch() {
return new ProxyErrorListener(getErrorListeners());
}
// subclass needs to override these if there are sempreds or actions

View File

@ -183,8 +183,8 @@ public class RuleContext implements ParseTree.RuleNode {
* that they are now going to track perfectly together. Once they
* converged on state 21, there is no way they can separate. In other
* words, the prior stack state is not consulted when computing where to
* go in the closure operation. ?$ and ??$ are considered the same stack.
* If ? is popped off then $ and ?$ remain; they are now an empty and
* go in the closure operation. x$ and xy$ are considered the same stack.
* If x is popped off then $ and y$ remain; they are now an empty and
* nonempty context comparison. So, if one stack is a suffix of
* another, then it will still degenerate to the simple empty stack
* comparison case.
@ -270,7 +270,9 @@ public class RuleContext implements ParseTree.RuleNode {
public void save(Parser parser, String fileName)
throws IOException, PrintException
{
Trees.writePS(this, parser, fileName);
// TreeViewer viewer = new TreeViewer(parser, this);
// viewer.save(fileName);
Trees.writePS(this, parser, fileName); // parrt routine
}
public void save(Parser parser, String fileName,

View File

@ -54,7 +54,7 @@ public interface Token {
/** Anything on different channel than DEFAULT_CHANNEL is not parsed
* by parser.
*/
public static final int HIDDEN_CHANNEL = 99;
public static final int HIDDEN_CHANNEL = 1;
/** Get the text of the token */
String getText();

View File

@ -36,24 +36,36 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
/** Do not buffer up the entire char stream. It does keep a small buffer
* for efficiency and also buffers while a mark exists (set by the
* lookahead prediction in parser). "Unbuffered" here refers to fact
* that it doesn't buffer all data, not that's it's on demand loading of char.
*/
public class UnbufferedCharStream implements CharStream {
/** A buffer of the data being scanned */
/** A moving window buffer of the data being scanned. While there's a
* marker, we keep adding to buffer. Otherwise, consume() resets
* so we start filling at index 0 again.
*/
protected char[] data;
/** How many characters are actually in the buffer */
/** How many characters are actually in the buffer; this is not
the buffer size, that's data.length.
*/
protected int n;
/** 0..n-1 index into string of next char */
/** 0..n-1 index into data of next char; data[p] is LA(1). */
protected int p=0;
protected int earliestMarker = -1;
/** Absolute char index. It's the index of the char about to be
* read via LA(1). Goes from 0 to numchar-1.
* read via LA(1). Goes from 0 to numchar-1 in entire stream.
*/
protected int currentCharIndex = 0;
/** Buf is window into stream. This is absolute index of data[0] */
/** Buf is window into stream. This is absolute char index into entire
* stream of data[0]
*/
protected int bufferStartIndex = 0;
protected Reader input;
@ -61,30 +73,35 @@ public class UnbufferedCharStream implements CharStream {
/** What is name or source of this char stream? */
public String name;
public UnbufferedCharStream(InputStream input) {
this(input, 256);
}
/** Useful for subclasses that pull char from other than this.input. */
public UnbufferedCharStream() {
this(256);
}
public UnbufferedCharStream(Reader input) {
this(input, 256);
}
public UnbufferedCharStream(InputStream input, int bufferSize) {
this.input = new InputStreamReader(input);
data = new char[bufferSize];
}
public UnbufferedCharStream(Reader input, int bufferSize) {
this.input = input;
data = new char[bufferSize];
}
public void reset() {
p = 0;
earliestMarker = -1;
currentCharIndex = 0;
bufferStartIndex = 0;
/** Useful for subclasses that pull char from other than this.input. */
public UnbufferedCharStream(int bufferSize) {
n = 0;
data = new char[bufferSize];
}
public UnbufferedCharStream(InputStream input) {
this(input, 256);
}
public UnbufferedCharStream(Reader input) {
this(input, 256);
}
public UnbufferedCharStream(InputStream input, int bufferSize) {
this(bufferSize);
this.input = new InputStreamReader(input);
fill(1); // prime
}
public UnbufferedCharStream(Reader input, int bufferSize) {
this(bufferSize);
this.input = input;
fill(1); // prime
}
@Override
@ -99,6 +116,7 @@ public class UnbufferedCharStream implements CharStream {
n = 0;
bufferStartIndex = currentCharIndex;
}
sync(1);
}
/** Make sure we have 'need' elements from current position p. Last valid
@ -114,7 +132,7 @@ public class UnbufferedCharStream implements CharStream {
public void fill(int n) {
for (int i=1; i<=n; i++) {
try {
int c = input.read();
int c = nextChar();
add(c);
}
catch (IOException ioe) {
@ -123,7 +141,12 @@ public class UnbufferedCharStream implements CharStream {
}
}
protected void add(int c) {
/** Override to provide different source of characters than this.input */
protected int nextChar() throws IOException {
return input.read();
}
protected void add(int c) {
if ( n>=data.length ) {
char[] newdata = new char[data.length*2]; // resize
System.arraycopy(data, 0, newdata, 0, data.length);
@ -154,19 +177,24 @@ public class UnbufferedCharStream implements CharStream {
throw new IllegalArgumentException("can't set marker earlier than previous existing marker: "+p+"<"+ earliestMarker);
}
if ( earliestMarker < 0 ) earliestMarker = m; // set first marker
// StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
// System.out.println(stackTrace[2].getMethodName()+": mark " + m);
return m;
}
/** Release can get markers in weird order since we reset p to beginning
* of buffer. Might mark at 1 and then at release p = 0 etc... Don't
* look for errors. Just reset earliestMarker if needed.
* @param marker
*/
@Override
public void release(int marker) {
// StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
// System.out.println(stackTrace[2].getMethodName()+": release " + marker);
// release is noop unless we remove earliest. then we don't need to
// keep anything in buffer. We only care about earliest. Releasing
// marker other than earliest does nothing as we can just keep in
// buffer.
if ( marker < earliestMarker || marker >= n ) {
throw new IllegalArgumentException("invalid marker: "+
marker+" not in "+0+".."+n);
}
if ( marker == earliestMarker) earliestMarker = -1;
}
@ -193,15 +221,30 @@ public class UnbufferedCharStream implements CharStream {
@Override
public String getSourceName() {
return name;
}
return name;
}
@Override
public String getText(Interval interval) {
@Override
public String getText(Interval interval) {
if (interval.a < bufferStartIndex || interval.b >= bufferStartIndex + n) {
throw new UnsupportedOperationException();
throw new UnsupportedOperationException("interval "+interval+" outside buffer: "+
bufferStartIndex+".."+(bufferStartIndex+n));
}
return new String(data, interval.a, interval.length());
}
}
/** For testing. What's in moving window into data stream? */
public String getBuffer() {
if ( n==0 ) return null;
return new String(data,0,n);
}
public int getBufferStartIndex() {
return bufferStartIndex;
}
public int getCurrentCharIndex() {
return currentCharIndex;
}
}

View File

@ -1,135 +1,212 @@
/*
[The "BSD license"]
Copyright (c) 2011 Terence Parr
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.runtime;
import org.antlr.v4.runtime.misc.Interval;
import org.antlr.v4.runtime.misc.LookaheadStream;
/** A token stream that pulls tokens from the source on-demand and
* without tracking a complete buffer of the tokens. This stream buffers
* the minimum number of tokens possible.
*
* You can't use this stream if you pass whitespace or other off-channel
* tokens to the parser. The stream can't ignore off-channel tokens.
*
* You can only look backwards 1 token: LT(-1).
*
* Use this when you need to read from a socket or other infinite stream.
*
* @see BufferedTokenStream
* @see CommonTokenStream
*/
public class UnbufferedTokenStream<T extends Token>
extends LookaheadStream<T>
implements TokenStream
{
import java.util.Arrays;
import java.util.List;
public class UnbufferedTokenStream<T extends Token> implements TokenStream {
protected TokenSource tokenSource;
protected int tokenIndex = 0; // simple counter to set token index in tokens
/** A moving window buffer of the data being scanned. While there's a
* marker, we keep adding to buffer. Otherwise, consume() resets
* so we start filling at index 0 again.
*/
protected Token[] tokens;
/** How many tokens are actually in the buffer; this is not
* the buffer size, that's tokens.length.
*/
protected int n;
/** 0..n-1 index into tokens of next token; tokens[p] is LA(1). */
protected int p=0;
protected int earliestMarker = -1;
/** Absolute token index. It's the index of the token about to be
* read via LA(1). Goes from 0 to numtokens-1 in entire stream.
*/
protected int currentTokenIndex = 0; // simple counter to set token index in tokens
/** Buf is window into stream. This is absolute token index into entire
* stream of tokens[0]
*/
protected int bufferStartTokenIndex = 0;
/** Skip tokens on any channel but this one; this is how we skip whitespace... */
// TODO: skip off-channel tokens!!!
protected int channel = Token.DEFAULT_CHANNEL;
public UnbufferedTokenStream(TokenSource tokenSource) {
this(tokenSource, 256);
}
public UnbufferedTokenStream(TokenSource tokenSource, int bufferSize) {
this.tokenSource = tokenSource;
tokens = new Token[bufferSize];
fill(1); // prime the pump
}
@Override
public T nextElement() {
T t = (T)tokenSource.nextToken();
if ( t instanceof WritableToken ) {
((WritableToken)t).setTokenIndex(tokenIndex);
}
tokenIndex++;
return t;
@Override
public Token get(int i) {
return null;
}
@Override
public boolean isEOF(Token o) {
return false;
}
@Override
public Token LT(int i) {
sync(i);
int index = p + i - 1;
if ( index < 0 || index > n ) throw new IndexOutOfBoundsException();
return tokens[index];
}
@Override
public TokenSource getTokenSource() { return tokenSource; }
@Override
public int LA(int i) { return LT(i).getType(); }
@Override
public TokenSource getTokenSource() {
return null;
}
@Override
public String getText() {
return null;
}
@Override
public String getText(RuleContext ctx) {
return null;
}
@Override
public String getText(Token start, Token stop) {
return null;
}
@Override
public void consume() {
p++;
currentTokenIndex++;
// have we hit end of buffer when no markers?
if ( p==n && earliestMarker < 0 ) {
// if so, it's an opportunity to start filling at index 0 again
// System.out.println("p=="+n+", no marker; reset buf start index="+currentCharIndex);
p = 0;
n = 0;
bufferStartTokenIndex = currentTokenIndex;
}
sync(1);
}
/** Make sure we have 'need' elements from current position p. Last valid
* p index is tokens.size()-1. p+need-1 is the tokens index 'need' elements
* ahead. If we need 1 element, (p+1-1)==p must be < tokens.size().
*/
protected void sync(int want) {
int need = (p+want-1) - n + 1; // how many more elements we need?
if ( need > 0 ) fill(need); // out of elements?
}
/** add n elements to buffer */
public void fill(int n) {
for (int i=1; i<=n; i++) {
Token t = tokenSource.nextToken();
if ( t instanceof WritableToken ) {
((WritableToken)t).setTokenIndex(currentTokenIndex);
}
add(t);
}
}
protected void add(Token t) {
if ( n>=tokens.length ) {
Token[] newtokens = new Token[tokens.length*2]; // resize
System.arraycopy(tokens, 0, newtokens, 0, tokens.length);
tokens = newtokens;
}
tokens[n++] = t;
}
/** Return a marker that we can release later. Marker happens to be
* index into buffer (not index()).
*/
@Override
public int mark() {
int m = p;
if ( p < earliestMarker) {
// they must have done seek to before min marker
throw new IllegalArgumentException("can't set marker earlier than previous existing marker: "+p+"<"+ earliestMarker);
}
if ( earliestMarker < 0 ) earliestMarker = m; // set first marker
return m;
}
@Override
public void release(int marker) {
// release is noop unless we remove earliest. then we don't need to
// keep anything in buffer. We only care about earliest. Releasing
// marker other than earliest does nothing as we can just keep in
// buffer.
if ( marker < earliestMarker || marker >= n ) {
throw new IllegalArgumentException("invalid marker: "+
marker+" not in "+0+".."+n);
}
if ( marker == earliestMarker) earliestMarker = -1;
}
@Override
public int index() {
return p + bufferStartTokenIndex;
}
@Override
public void seek(int index) {
// index == to bufferStartIndex should set p to 0
int i = index - bufferStartTokenIndex;
if ( i < 0 || i >= n ) {
throw new UnsupportedOperationException("seek to index outside buffer: "+
index+" not in "+ bufferStartTokenIndex +".."+(bufferStartTokenIndex +n));
}
p = i;
}
@Override
public int size() {
throw new UnsupportedOperationException("Unbuffered stream cannot know its size");
}
@Override
public String getSourceName() {
return tokenSource.getSourceName();
}
@Override
public String getText(Interval interval) {
int bufferStartIndex = currentElementIndex - p;
int bufferStopIndex = bufferStartIndex + data.size() - 1;
int bufferStartIndex = currentTokenIndex - p;
int bufferStopIndex = bufferStartIndex + tokens.length - 1;
int start = interval.a;
int stop = interval.b;
if (start < bufferStartIndex || stop > bufferStopIndex) {
throw new UnsupportedOperationException();
throw new UnsupportedOperationException("interval "+interval+" not in token buffer window: "+
bufferStartIndex+".."+bufferStopIndex);
}
StringBuilder buf = new StringBuilder();
for (int i = start; i <= stop; i++) {
T t = data.get(i - bufferStartIndex);
Token t = tokens[i - bufferStartIndex];
buf.append(t.getText());
}
return buf.toString();
}
@Override
public String getText() {
return getText(Interval.of(0,index()));
/** For testing. What's in moving window into tokens stream? */
public List<T> getBuffer() {
if ( n==0 ) return null;
return (List<T>)Arrays.asList(Arrays.copyOfRange(tokens, 0, n));
}
@Override
public String getText(RuleContext ctx) {
return getText(ctx.getSourceInterval());
}
@Override
public String getText(Token start, Token stop) {
if ( start!=null && stop!=null ) {
return getText(Interval.of(start.getTokenIndex(), stop.getTokenIndex()));
}
return null;
}
@Override
public int LA(int i) { return LT(i).getType(); }
@Override
public T get(int i) {
int bufferStartIndex = currentElementIndex - p;
int bufferStopIndex = bufferStartIndex + data.size() - 1;
if (i < bufferStartIndex || i > bufferStopIndex) {
throw new UnsupportedOperationException();
}
return data.get(i - bufferStartIndex);
}
@Override
public String getSourceName() { return tokenSource.getSourceName(); }
}

View File

@ -119,7 +119,7 @@ public class ATN {
}
public DecisionState getDecisionState(int decision) {
if ( decisionToState.size()>0 ) {
if ( !decisionToState.isEmpty() ) {
return decisionToState.get(decision);
}
return null;

View File

@ -41,6 +41,53 @@ import java.util.Set;
/** Specialized OrderedHashSet that can track info about the set.
* Might be able to optimize later w/o affecting code that uses this set.
*
* Track configs by alt so we can compress those context trees.
*
* Sam's sharing: 2 configs that have same state, same alt, same sem ctx:
* that's one atn config. ATNConfig is node in graph. context graph ptr is
* what you share.
*
* equals: must remember comparing two nodes, save true/false to avoid
* recomputing lest even graph is same cost to compare as tree. graph
* enum of paths is same cost of tree.
*
* in full ctx, cannot trim suffixes but we still share.
* merge case that looks like suffix:
* start at s with [] then can get [10] [10 4]. graph looks like
* 10->4, 10 also points to EMPTY.
*
* example.
* a b d
* a b c
* what if a's are different nodes? must join
* what if we want to add e c d?
*
* might be merging two graphs. crap:
* a b d
e b d
a c d
e c d
another case:
a b d
e b d
a b d d
e b d d
think about a map that is adjacency list
ours is more complciated due to local ctx. tomita is always doing full ctx
so no worries about suffix.
merge on graph is the key so that we can call rule and have graph as parent:
c calls b calls a, etc...
a->b->c
|->b->d
|->b->e
now with this config, we call another, it just points at a.
*/
public class ATNConfigSet implements Set<ATNConfig> {
public static class Key {
@ -159,10 +206,11 @@ public class ATNConfigSet implements Set<ATNConfig> {
@Override
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append(elements().toString());
if ( hasSemanticContext ) buf.append(",hasSemanticContext="+hasSemanticContext);
if ( uniqueAlt!=ATN.INVALID_ALT_NUMBER ) buf.append(",uniqueAlt="+uniqueAlt);
if ( conflictingAlts!=null ) buf.append(",conflictingAlts="+conflictingAlts);
// buf.append(elements().toString());
buf.append(super.toString());
if ( hasSemanticContext ) buf.append(",hasSemanticContext=").append(hasSemanticContext);
if ( uniqueAlt!=ATN.INVALID_ALT_NUMBER ) buf.append(",uniqueAlt=").append(uniqueAlt);
if ( conflictingAlts!=null ) buf.append(",conflictingAlts=").append(conflictingAlts);
if ( dipsIntoOuterContext ) buf.append(",dipsIntoOuterContext");
return buf.toString();
}

View File

@ -112,7 +112,7 @@ public class ParserATNPathFinder extends ParserATNSimulator<Token> {
int n = s.getNumberOfTransitions();
boolean aGoodPath = false;
TraceTree found = null;
TraceTree found;
for (int j=0; j<n; j++) {
Transition t = s.transition(j);
if ( t.getClass() == RuleTransition.class ) {
@ -165,7 +165,7 @@ public class ParserATNPathFinder extends ParserATNSimulator<Token> {
TraceTree root, Transition t)
{
SemanticContext.Predicate pred = ((PredicateTransition) t).getPredicate();
boolean pass = false;
boolean pass;
if ( pred.isCtxDependent ) {
if ( ctx instanceof ParserRuleContext && ctx==initialContext ) {
System.out.println("eval pred "+pred+"="+pred.eval(parser, ctx));

View File

@ -772,7 +772,7 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
return st.target;
}
}
else if ( trans instanceof RangeTransition ) {
else if ( trans instanceof RangeTransition ) { // TODO: can't happen in parser, right? remove
RangeTransition rt = (RangeTransition)trans;
if ( ttype>=rt.from && ttype<=rt.to ) return rt.target;
}

View File

@ -125,7 +125,7 @@ public abstract class SemanticContext {
}
@Override
public boolean equals(@NotNull Object obj) {
public boolean equals(Object obj) {
if ( this==obj ) return true;
if ( !(obj instanceof AND) ) return false;
AND other = (AND)obj;
@ -162,7 +162,7 @@ public abstract class SemanticContext {
}
@Override
public boolean equals(@NotNull Object obj) {
public boolean equals(Object obj) {
if ( this==obj ) return true;
if ( !(obj instanceof OR) ) return false;
OR other = (OR)obj;

View File

@ -60,7 +60,7 @@ public class DFASerializer {
if ( t!=null && t.stateNumber != Integer.MAX_VALUE ) {
buf.append(getStateString(s));
String label = getEdgeLabel(i);
buf.append("-"+label+"->"+ getStateString(t)+'\n');
buf.append("-").append(label).append("->").append(getStateString(t)).append('\n');
}
}
}

View File

@ -186,6 +186,11 @@ public class DFAState {
public boolean equals(Object o) {
// compare set of ATN configurations in this set with other
if ( this==o ) return true;
if (!(o instanceof DFAState)) {
return false;
}
DFAState other = (DFAState)o;
// TODO (sam): what to do when configs==null?
boolean sameSet = this.configset.equals(other.configset);
@ -196,7 +201,7 @@ public class DFAState {
@Override
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append(stateNumber + ":" + configset);
buf.append(stateNumber).append(":").append(configset);
if ( isAcceptState ) {
buf.append("=>");
if ( predicates!=null ) {

View File

@ -1,100 +0,0 @@
/*
[The "BSD license"]
Copyright (c) 2011 Terence Parr
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.runtime.misc;
import java.util.*;
/** A queue that can dequeue and get(i) in O(1) and grow arbitrarily large.
* A linked list is fast at dequeue but slow at get(i). An array is
* the reverse. This is O(1) for both operations.
*
* List grows until you dequeue last element at end of buffer. Then
* it resets to start filling at 0 again. If adds/removes are balanced, the
* buffer will not grow too large.
*
* No iterator stuff as that's not how we'll use it.
*/
public class FastQueue<T> {
/** dynamically-sized buffer of elements */
protected List<T> data = new ArrayList<T>();
/** index of next element to fill */
protected int p = 0;
protected int range = -1; // how deep have we gone?
public void reset() { clear(); }
public void clear() { p = 0; data.clear(); }
/** Get and remove first element in queue */
public T remove() {
T o = elementAt(0);
p++;
// have we hit end of buffer?
if ( p == data.size() ) {
// if so, it's an opportunity to start filling at index 0 again
clear(); // size goes to 0, but retains memory
}
return o;
}
public void add(T o) { data.add(o); }
public int size() { return data.size() - p; }
public int range() { return range; }
public T head() { return elementAt(0); }
/** Return element i elements ahead of current element. i==0 gets
* current element. This is not an absolute index into the data list
* since p defines the start of the real list.
*/
public T elementAt(int i) {
int absIndex = p + i;
if ( absIndex >= data.size() ) {
throw new NoSuchElementException("queue index "+ absIndex +" > last index "+(data.size()-1));
}
if ( absIndex < 0 ) {
throw new NoSuchElementException("queue index "+ absIndex +" < 0");
}
if ( absIndex>range ) range = absIndex;
return data.get(absIndex);
}
/** Return string of current buffer contents; non-destructive */
@Override
public String toString() {
StringBuilder buf = new StringBuilder();
int n = size();
for (int i=0; i<n; i++) {
buf.append(elementAt(i));
if ( (i+1)<n ) buf.append(" ");
}
return buf.toString();
}
}

View File

@ -30,7 +30,12 @@
package org.antlr.v4.runtime.misc;
import javax.imageio.ImageIO;
import javax.print.*;
import javax.print.DocFlavor;
import javax.print.DocPrintJob;
import javax.print.PrintException;
import javax.print.PrintService;
import javax.print.SimpleDoc;
import javax.print.StreamPrintServiceFactory;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.swing.*;
@ -41,6 +46,7 @@ import java.awt.print.Printable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
public class GraphicsSupport {
/**
@ -74,11 +80,12 @@ public class GraphicsSupport {
public static void saveImage(final JComponent comp, String fileName)
throws IOException, PrintException
{
if (fileName.endsWith(".ps") || fileName.endsWith(".eps")) {
if (fileName.endsWith(".ps") || fileName.endsWith(".eps") ) {
DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PRINTABLE;
String mimeType = "application/postscript";
StreamPrintServiceFactory[] factories =
StreamPrintServiceFactory.lookupStreamPrintServiceFactories(flavor, mimeType);
System.out.println(Arrays.toString(factories));
FileOutputStream out = new FileOutputStream(fileName);
if (factories.length > 0) {
PrintService service = factories[0].getPrintService(out);
@ -87,13 +94,17 @@ public class GraphicsSupport {
public int print(Graphics g, PageFormat pf, int page) {
if (page >= 1) return Printable.NO_SUCH_PAGE;
else {
double sf1 = pf.getImageableWidth() / (comp.getWidth() + 1);
double sf2 = pf.getImageableHeight() / (comp.getHeight() + 1);
double s = Math.min(sf1, sf2);
Graphics2D g2 = (Graphics2D) g;
g2.translate((pf.getWidth() - pf.getImageableWidth()) / 2,
(pf.getHeight() - pf.getImageableHeight()) / 2);
g2.scale(s, s);
if ( comp.getWidth() > pf.getImageableWidth() ||
comp.getHeight() > pf.getImageableHeight() )
{
double sf1 = pf.getImageableWidth() / (comp.getWidth() + 1);
double sf2 = pf.getImageableHeight() / (comp.getHeight() + 1);
double s = Math.min(sf1, sf2);
g2.scale(s, s);
}
comp.paint(g);
return Printable.PAGE_EXISTS;
@ -105,16 +116,20 @@ public class GraphicsSupport {
job.print(doc, attributes);
}
} else {
// parrt: works with [image/jpeg, image/png, image/x-png, image/vnd.wap.wbmp, image/bmp, image/gif]
Rectangle rect = comp.getBounds();
BufferedImage image = new BufferedImage(rect.width, rect.height,
BufferedImage.TYPE_INT_RGB);
Graphics2D g = (Graphics2D) image.getGraphics();
g.setColor(Color.WHITE);
g.fill(rect);
g.setColor(Color.BLACK);
// g.setColor(Color.BLACK);
comp.paint(g);
String extension = fileName.substring(fileName.lastIndexOf('.') + 1);
ImageIO.write(image, extension, new File(fileName));
boolean result = ImageIO.write(image, extension, new File(fileName));
if ( !result ) {
System.err.println("Now imager for " + extension);
}
g.dispose();
}
}

View File

@ -90,8 +90,8 @@ public class LogManager {
}
public String save() throws IOException {
String dir = System.getProperty("java.io.tmpdir");
dir = ".";
//String dir = System.getProperty("java.io.tmpdir");
String dir = ".";
String defaultFilename =
dir + "/antlr-" +
new SimpleDateFormat("yyyy-MM-dd-HH.mm.ss").format(new Date()) + ".log";

View File

@ -1,175 +0,0 @@
/*
[The "BSD license"]
Copyright (c) 2011 Terence Parr
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.runtime.misc;
import java.util.NoSuchElementException;
/** A lookahead queue that knows how to mark/release locations
* in the buffer for backtracking purposes. Any markers force the FastQueue
* superclass to keep all tokens until no more markers; then can reset
* to avoid growing a huge buffer.
*/
public abstract class LookaheadStream<T> extends FastQueue<T> {
public static final int UNINITIALIZED_EOF_ELEMENT_INDEX = Integer.MAX_VALUE;
/** Absolute token index. It's the index of the symbol about to be
* read via LT(1). Goes from 0 to numtokens.
*/
protected int currentElementIndex = 0;
protected T prevElement;
/** Track object returned by nextElement upon end of stream;
* Return it later when they ask for LT passed end of input.
*/
public T eof = null;
/** tracks how deep mark() calls are nested */
protected int markDepth = 0;
@Override
public void reset() {
super.reset();
currentElementIndex = 0;
p = 0;
prevElement=null;
}
/** Implement nextElement to supply a stream of elements to this
* lookahead buffer. Return eof upon end of the stream we're pulling from.
*/
public abstract T nextElement();
public abstract boolean isEOF(T o);
/** Get and remove first element in queue; override FastQueue.remove();
* it's the same, just checks for backtracking.
*/
@Override
public T remove() {
T o = elementAt(0);
p++;
// have we hit end of buffer and not backtracking?
if ( p == data.size() && markDepth==0 ) {
// if so, it's an opportunity to start filling at index 0 again
clear(); // size goes to 0, but retains memory
}
return o;
}
/** Make sure we have at least one element to remove, even if EOF */
public void consume() {
syncAhead(1);
T element = remove();
if (markDepth == 0) {
prevElement = element;
}
currentElementIndex++;
}
/** Make sure we have 'need' elements from current position p. Last valid
* p index is data.size()-1. p+need-1 is the data index 'need' elements
* ahead. If we need 1 element, (p+1-1)==p must be < data.size().
*/
protected void syncAhead(int need) {
int n = (p+need-1) - data.size() + 1; // how many more elements we need?
if ( n > 0 ) fill(n); // out of elements?
}
/** add n elements to buffer */
public void fill(int n) {
for (int i=1; i<=n; i++) {
T o = nextElement();
if ( isEOF(o) ) eof = o;
data.add(o);
}
}
/** Size of entire stream is unknown; we only know buffer size from FastQueue */
@Override
public int size() { throw new UnsupportedOperationException("streams are of unknown size"); }
public T LT(int k) {
if ( k==0 ) {
return null;
}
if ( k<0 ) return LB(-k);
//System.out.print("LT(p="+p+","+k+")=");
syncAhead(k);
if ( (p+k-1) > data.size() ) return eof;
return elementAt(k-1);
}
public int index() { return currentElementIndex; }
public int mark() {
markDepth++;
return markDepth;
}
public void release(int marker) {
// no resources to release
}
/** Seek to a 0-indexed position within data buffer. Can't handle
* case where you seek beyond end of existing buffer. Normally used
* to seek backwards in the buffer. Does not force loading of nodes.
* Doesn't seek to absolute position in input stream since this stream
* is unbuffered. Seeks only into our moving window of elements.
*/
public void seek(int index) {
int bufferStartIndex = currentElementIndex - p;
if (index < bufferStartIndex) {
throw new UnsupportedOperationException("Cannot seek to the specified index.");
}
if (index > currentElementIndex) {
int startElementIndex = currentElementIndex;
for (int i = 0; i < index - startElementIndex; i++) {
consume();
}
}
else {
currentElementIndex = index;
p = index - bufferStartIndex;
}
}
protected T LB(int k) {
int bufferIndex = p - k;
if (bufferIndex == -1) {
return prevElement;
}
else if (bufferIndex >= 0 && bufferIndex < data.size()) {
return data.get(bufferIndex);
}
throw new NoSuchElementException("can't look backwards more than one token in this stream");
}
}

View File

@ -94,6 +94,10 @@ public class OrderedHashSet<T> extends LinkedHashSet<T> {
@Override
public boolean equals(Object o) {
if (!(o instanceof OrderedHashSet<?>)) {
return false;
}
// System.out.print("equals " + this + ", " + o+" = ");
boolean same = elements!=null && elements.equals(((OrderedHashSet<?>)o).elements);
// System.out.println(same);

View File

@ -50,7 +50,7 @@ import java.lang.reflect.Method;
* postscript file. Optionally taking input file.
*
* $ java org.antlr.v4.runtime.misc.TestRig GrammarName startRuleName
* [-print]
* [-tree]
* [-tokens] [-gui] [-ps file.ps]
* [-trace]
* [-diagnostics]
@ -73,7 +73,7 @@ public class TestRig {
String encoding = null;
if ( args.length < 2 ) {
System.err.println("java org.antlr.v4.runtime.misc.TestRig GrammarName startRuleName\n" +
" [-tokens] [-print] [-gui] [-ps file.ps] [-encoding encodingname]\n" +
" [-tokens] [-tree] [-gui] [-ps file.ps] [-encoding encodingname]\n" +
" [-trace] [-diagnostics]\n"+
" [input-filename]");
System.err.println("Use startRuleName='tokens' if GrammarName is a lexer grammar.");
@ -92,7 +92,7 @@ public class TestRig {
inputFile = arg;
continue;
}
if ( arg.equals("-print") ) {
if ( arg.equals("-tree") ) {
printTree = true;
}
if ( arg.equals("-gui") ) {
@ -127,7 +127,7 @@ public class TestRig {
// System.out.println("exec "+grammarName+"."+startRuleName);
String lexerName = grammarName+"Lexer";
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Class lexerClass = null;
Class lexerClass;
try {
lexerClass = cl.loadClass(lexerName);
}
@ -138,6 +138,7 @@ public class TestRig {
}
if ( lexerClass==null ) {
System.err.println("Can't load "+lexerName);
return;
}
InputStream is = System.in;

View File

@ -87,7 +87,7 @@ public class TraceTree implements Tree {
states.add(0, p.state);
p = p.parent;
}
if ( states.size()==0 ) return null;
if ( states.isEmpty() ) return null;
return states;
}

View File

@ -74,7 +74,7 @@ public class PostScriptDocument {
protected StringBuilder header() {
StringBuilder b = new StringBuilder();
b.append("%!PS-Adobe-3.0 EPSF-3.0\n");
b.append(boundingBox+"\n");
b.append(boundingBox).append("\n");
b.append("0.3 setlinewidth\n");
b.append("%% x y w h highlight\n" +
"/highlight {\n" +
@ -116,7 +116,7 @@ public class PostScriptDocument {
public void lineWidth(double w) {
lineWidth = w;
ps.append(w+" setlinewidth\n");
ps.append(w).append(" setlinewidth\n");
}
public void move(double x, double y) {

View File

@ -34,11 +34,13 @@ import org.abego.treelayout.TreeForTreeLayout;
import org.abego.treelayout.TreeLayout;
import org.abego.treelayout.util.DefaultConfiguration;
import org.antlr.v4.runtime.Parser;
import org.antlr.v4.runtime.misc.GraphicsSupport;
import org.antlr.v4.runtime.misc.Utils;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.Tree;
import org.antlr.v4.runtime.tree.Trees;
import javax.print.PrintException;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
@ -47,6 +49,7 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.CubicCurve2D;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
@ -324,7 +327,6 @@ public class TreeViewer extends JComponent {
});
}
/** This does not always seem to render the postscript properly
public void save(String fileName) throws IOException, PrintException {
JDialog dialog = new JDialog();
Container contentPane = dialog.getContentPane();
@ -335,10 +337,8 @@ public class TreeViewer extends JComponent {
dialog.pack();
dialog.setLocationRelativeTo(null);
dialog.dispose();
// dialog.setVisible(true);
GraphicsSupport.saveImage(this, fileName);
}
*/
// ---------------------------------------------------

View File

@ -1,5 +1,8 @@
lexer grammar T;
grammar T;
A : 'a' {false}? ;
B : 'a' ;
WS : [ \n] ;
s : ID b ;
b : INT ;
ID : [a-zA-Z]+ ;
INT : [0-9]+ ;
WS : [ \t\n\r]+ -> skip ;

View File

@ -1,13 +1,30 @@
import org.antlr.v4.runtime.ANTLRFileStream;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CommonTokenFactory;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.UnbufferedCharStream;
import java.io.FileInputStream;
import java.io.InputStream;
public class TestT {
public static void main(String[] args) throws Exception {
CharStream input = new ANTLRFileStream(args[0]);
T lex = new T(input);
String inputFile = null;
if ( args.length>0 ) inputFile = args[0];
InputStream is = System.in;
if ( inputFile!=null ) {
is = new FileInputStream(inputFile);
}
CharStream input = new UnbufferedCharStream(is);
TLexer lex = new TLexer(input);
lex.setTokenFactory(new CommonTokenFactory(true));
CommonTokenStream tokens = new CommonTokenStream(lex);
tokens.fill();
System.out.println(tokens.getTokens());
TParser parser = new TParser(tokens);
ParserRuleContext tree = parser.s();
tree.save(parser, "/tmp/t.ps");
}
}

View File

@ -123,8 +123,7 @@ public <if(parser.abstractRecognizer)>abstract <endif>class <parser.name> extend
<parser.tokens:{k | <k>=<parser.tokens.(k)>}; separator=", ", wrap, anchor>;
<endif>
public static final String[] tokenNames = {
"\<INVALID>",
<parser.tokenNames:{t | <t>}; separator=", ", wrap, anchor>
<parser.tokenNames:{t | <t>}; null="\"\<INVALID>\"", separator=", ", wrap, anchor>
};
public static final int
<parser.rules:{r | RULE_<r.name> = <r.index>}; separator=", ", wrap, anchor>;

View File

@ -128,7 +128,7 @@ public class Tool {
public static Option[] optionDefs = {
new Option("outputDirectory", "-o", OptionArgType.STRING, "specify output directory where all output is generated"),
new Option("libDirectory", "-lib", OptionArgType.STRING, "specify location of .token files"),
new Option("libDirectory", "-lib", OptionArgType.STRING, "specify location of grammars, tokens files"),
new Option("report", "-report", "print out a report about the grammar(s) processed"),
new Option("printGrammar", "-print", "print out the grammar without actions"),
new Option("debug", "-debug", "generate a parser that emits debugging events"),
@ -306,8 +306,8 @@ public class Tool {
GrammarTransformPipeline transform = new GrammarTransformPipeline(g, this);
transform.process();
LexerGrammar lexerg = null;
GrammarRootAST lexerAST = null;
LexerGrammar lexerg;
GrammarRootAST lexerAST;
if ( g.ast!=null && g.ast.grammarType== ANTLRParser.COMBINED &&
!g.ast.hasErrors )
{

View File

@ -49,7 +49,7 @@ public class AnalysisPipeline {
// LEFT-RECURSION CHECK
LeftRecursionDetector lr = new LeftRecursionDetector(g, g.atn);
lr.check();
if ( lr.listOfRecursiveCycles.size()>0 ) return; // bail out
if ( !lr.listOfRecursiveCycles.isEmpty() ) return; // bail out
// BUILD DFA FOR EACH DECISION
if ( !g.isLexer() ) processParser();

View File

@ -29,11 +29,20 @@
package org.antlr.v4.analysis;
import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.atn.ATN;
import org.antlr.v4.runtime.atn.ATNState;
import org.antlr.v4.runtime.atn.RuleStartState;
import org.antlr.v4.runtime.atn.RuleStopState;
import org.antlr.v4.runtime.atn.RuleTransition;
import org.antlr.v4.runtime.atn.Transition;
import org.antlr.v4.runtime.misc.OrderedHashSet;
import org.antlr.v4.tool.*;
import org.antlr.v4.tool.Grammar;
import org.antlr.v4.tool.Rule;
import java.util.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class LeftRecursionDetector {
Grammar g;
@ -63,7 +72,7 @@ public class LeftRecursionDetector {
check(g.getRule(start.ruleIndex), start, new HashSet<ATNState>());
}
//System.out.println("cycles="+listOfRecursiveCycles);
if ( listOfRecursiveCycles.size()>0 ) {
if ( !listOfRecursiveCycles.isEmpty() ) {
g.tool.errMgr.leftRecursionCycles(g.fileName, listOfRecursiveCycles);
}
}

View File

@ -115,7 +115,7 @@ public class LeftRecursiveRuleTransformer {
String ruleName = prevRuleAST.getChild(0).getText();
LeftRecursiveRuleAnalyzer leftRecursiveRuleWalker =
new LeftRecursiveRuleAnalyzer(tokens, prevRuleAST, tool, ruleName, language);
boolean isLeftRec = false;
boolean isLeftRec;
try {
// System.out.println("TESTING ---------------\n"+
// leftRecursiveRuleWalker.text(ruleAST));

View File

@ -29,7 +29,23 @@
package org.antlr.v4.automata;
import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.atn.ATNState;
import org.antlr.v4.runtime.atn.ActionTransition;
import org.antlr.v4.runtime.atn.AtomTransition;
import org.antlr.v4.runtime.atn.BlockEndState;
import org.antlr.v4.runtime.atn.BlockStartState;
import org.antlr.v4.runtime.atn.EpsilonTransition;
import org.antlr.v4.runtime.atn.NotSetTransition;
import org.antlr.v4.runtime.atn.PlusBlockStartState;
import org.antlr.v4.runtime.atn.PlusLoopbackState;
import org.antlr.v4.runtime.atn.RuleStartState;
import org.antlr.v4.runtime.atn.RuleStopState;
import org.antlr.v4.runtime.atn.RuleTransition;
import org.antlr.v4.runtime.atn.SetTransition;
import org.antlr.v4.runtime.atn.StarBlockStartState;
import org.antlr.v4.runtime.atn.StarLoopEntryState;
import org.antlr.v4.runtime.atn.StarLoopbackState;
import org.antlr.v4.runtime.atn.Transition;
import org.antlr.v4.tool.Grammar;
import java.util.ArrayList;
@ -57,9 +73,9 @@ public class ATNPrinter {
work.add(start);
StringBuilder buf = new StringBuilder();
ATNState s = null;
ATNState s;
while ( work.size()>0 ) {
while ( !work.isEmpty() ) {
s = work.remove(0);
if ( marked.contains(s) ) continue;
int n = s.getNumberOfTransitions();
@ -73,33 +89,33 @@ public class ATNPrinter {
}
buf.append(getStateString(s));
if ( t instanceof EpsilonTransition ) {
buf.append("->"+ getStateString(t.target)+'\n');
buf.append("->").append(getStateString(t.target)).append('\n');
}
else if ( t instanceof RuleTransition ) {
buf.append("-"+g.getRule(((RuleTransition)t).ruleIndex).name+"->"+ getStateString(t.target)+'\n');
buf.append("-").append(g.getRule(((RuleTransition)t).ruleIndex).name).append("->").append(getStateString(t.target)).append('\n');
}
else if ( t instanceof ActionTransition ) {
ActionTransition a = (ActionTransition)t;
buf.append("-"+a.toString()+"->"+ getStateString(t.target)+'\n');
buf.append("-").append(a.toString()).append("->").append(getStateString(t.target)).append('\n');
}
else if ( t instanceof SetTransition ) {
SetTransition st = (SetTransition)t;
boolean not = st instanceof NotSetTransition;
if ( g.isLexer() ) {
buf.append("-"+(not?"~":"")+st.toString()+"->"+ getStateString(t.target)+'\n');
buf.append("-").append(not?"~":"").append(st.toString()).append("->").append(getStateString(t.target)).append('\n');
}
else {
buf.append("-"+(not?"~":"")+st.label().toString(g.getTokenNames())+"->"+ getStateString(t.target)+'\n');
buf.append("-").append(not?"~":"").append(st.label().toString(g.getTokenNames())).append("->").append(getStateString(t.target)).append('\n');
}
}
else if ( t instanceof AtomTransition ) {
AtomTransition a = (AtomTransition)t;
String label = a.toString();
if ( g!=null ) label = g.getTokenDisplayName(a.label);
buf.append("-"+label+"->"+ getStateString(t.target)+'\n');
buf.append("-").append(label).append("->").append(getStateString(t.target)).append('\n');
}
else {
buf.append("-"+t.toString()+"->"+ getStateString(t.target)+'\n');
buf.append("-").append(t.toString()).append("->").append(getStateString(t.target)).append('\n');
}
}
}

View File

@ -31,7 +31,18 @@ package org.antlr.v4.automata;
import org.antlr.v4.misc.Utils;
import org.antlr.v4.parse.ANTLRParser;
import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.atn.ATN;
import org.antlr.v4.runtime.atn.ATNSimulator;
import org.antlr.v4.runtime.atn.ATNState;
import org.antlr.v4.runtime.atn.ActionTransition;
import org.antlr.v4.runtime.atn.AtomTransition;
import org.antlr.v4.runtime.atn.DecisionState;
import org.antlr.v4.runtime.atn.LoopEndState;
import org.antlr.v4.runtime.atn.PredicateTransition;
import org.antlr.v4.runtime.atn.RangeTransition;
import org.antlr.v4.runtime.atn.RuleTransition;
import org.antlr.v4.runtime.atn.SetTransition;
import org.antlr.v4.runtime.atn.Transition;
import org.antlr.v4.runtime.misc.Interval;
import org.antlr.v4.runtime.misc.IntervalSet;
import org.antlr.v4.tool.Grammar;
@ -200,7 +211,7 @@ public class ATNSerializer {
int p = 0;
int grammarType = ATNSimulator.toInt(data[p++]);
int maxType = ATNSimulator.toInt(data[p++]);
buf.append("max type "+maxType+"\n");
buf.append("max type ").append(maxType).append("\n");
int nstates = ATNSimulator.toInt(data[p++]);
for (int i=1; i<=nstates; i++) {
int stype = ATNSimulator.toInt(data[p++]);
@ -211,9 +222,9 @@ public class ATNSerializer {
int loopBackStateNumber = ATNSimulator.toInt(data[p++]);
arg = " "+loopBackStateNumber;
}
buf.append((i - 1) + ":" +
ATNState.serializationNames.get(stype) + " "+
ruleIndex + arg + "\n");
buf.append(i - 1).append(":")
.append(ATNState.serializationNames.get(stype)).append(" ")
.append(ruleIndex).append(arg).append("\n");
}
int nrules = ATNSimulator.toInt(data[p++]);
for (int i=0; i<nrules; i++) {
@ -221,24 +232,24 @@ public class ATNSerializer {
if ( g.isLexer() ) {
int arg1 = ATNSimulator.toInt(data[p++]);
int arg2 = ATNSimulator.toInt(data[p++]);
buf.append("rule "+i+":"+s+" "+arg1+","+arg2+'\n');
buf.append("rule ").append(i).append(":").append(s).append(" ").append(arg1).append(",").append(arg2).append('\n');
}
else {
buf.append("rule "+i+":"+s+'\n');
buf.append("rule ").append(i).append(":").append(s).append('\n');
}
}
int nmodes = ATNSimulator.toInt(data[p++]);
for (int i=0; i<nmodes; i++) {
int s = ATNSimulator.toInt(data[p++]);
buf.append("mode "+i+":"+s+'\n');
buf.append("mode ").append(i).append(":").append(s).append('\n');
}
int nsets = ATNSimulator.toInt(data[p++]);
for (int i=1; i<=nsets; i++) {
int nintervals = ATNSimulator.toInt(data[p++]);
buf.append((i-1)+":");
buf.append(i-1).append(":");
for (int j=1; j<=nintervals; j++) {
if ( j>1 ) buf.append(", ");
buf.append(getTokenName(ATNSimulator.toInt(data[p]))+".."+getTokenName(ATNSimulator.toInt(data[p + 1])));
buf.append(getTokenName(ATNSimulator.toInt(data[p]))).append("..").append(getTokenName(ATNSimulator.toInt(data[p + 1])));
p += 2;
}
buf.append("\n");
@ -251,17 +262,17 @@ public class ATNSerializer {
int arg1 = ATNSimulator.toInt(data[p + 3]);
int arg2 = ATNSimulator.toInt(data[p + 4]);
int arg3 = ATNSimulator.toInt(data[p + 5]);
buf.append(src+"->"+trg+
" "+Transition.serializationNames.get(ttype)+
" "+arg1+","+arg2+","+arg3+
"\n");
buf.append(src).append("->").append(trg)
.append(" ").append(Transition.serializationNames.get(ttype))
.append(" ").append(arg1).append(",").append(arg2).append(",").append(arg3)
.append("\n");
p += 6;
}
int ndecisions = ATNSimulator.toInt(data[p++]);
for (int i=1; i<=ndecisions; i++) {
int s = ATNSimulator.toInt(data[p++]);
int isGreedy = ATNSimulator.toInt(data[p++]);
buf.append((i-1)+":"+s+" "+isGreedy+"\n");
buf.append(i-1).append(":").append(s).append(" ").append(isGreedy).append("\n");
}
return buf.toString();
}

View File

@ -31,16 +31,47 @@ package org.antlr.v4.codegen;
import org.antlr.runtime.tree.CommonTreeNodeStream;
import org.antlr.v4.analysis.LeftRecursiveRuleAltInfo;
import org.antlr.v4.codegen.model.*;
import org.antlr.v4.codegen.model.Action;
import org.antlr.v4.codegen.model.AltBlock;
import org.antlr.v4.codegen.model.BaseListenerFile;
import org.antlr.v4.codegen.model.BaseParseListenerFile;
import org.antlr.v4.codegen.model.BaseVisitorFile;
import org.antlr.v4.codegen.model.Choice;
import org.antlr.v4.codegen.model.CodeBlockForAlt;
import org.antlr.v4.codegen.model.CodeBlockForOuterMostAlt;
import org.antlr.v4.codegen.model.LabeledOp;
import org.antlr.v4.codegen.model.LeftRecursiveRuleFunction;
import org.antlr.v4.codegen.model.Lexer;
import org.antlr.v4.codegen.model.LexerFile;
import org.antlr.v4.codegen.model.ListenerFile;
import org.antlr.v4.codegen.model.OutputModelObject;
import org.antlr.v4.codegen.model.ParseListenerFile;
import org.antlr.v4.codegen.model.Parser;
import org.antlr.v4.codegen.model.ParserFile;
import org.antlr.v4.codegen.model.RuleActionFunction;
import org.antlr.v4.codegen.model.RuleFunction;
import org.antlr.v4.codegen.model.RuleSempredFunction;
import org.antlr.v4.codegen.model.SrcOp;
import org.antlr.v4.codegen.model.StarBlock;
import org.antlr.v4.codegen.model.VisitorFile;
import org.antlr.v4.codegen.model.decl.CodeBlock;
import org.antlr.v4.misc.Utils;
import org.antlr.v4.parse.*;
import org.antlr.v4.tool.*;
import org.antlr.v4.tool.ast.*;
import org.stringtemplate.v4.*;
import org.antlr.v4.parse.ANTLRParser;
import org.antlr.v4.parse.GrammarASTAdaptor;
import org.antlr.v4.tool.Alternative;
import org.antlr.v4.tool.Grammar;
import org.antlr.v4.tool.LeftRecursiveRule;
import org.antlr.v4.tool.Rule;
import org.antlr.v4.tool.ast.ActionAST;
import org.antlr.v4.tool.ast.BlockAST;
import org.antlr.v4.tool.ast.GrammarAST;
import org.antlr.v4.tool.ast.PredAST;
import org.stringtemplate.v4.ST;
import org.stringtemplate.v4.STGroup;
import java.util.*;
import org.antlr.runtime.RecognitionException;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
/** This receives events from SourceGenTriggers.g and asks factory to do work.
* Then runs extensions in order on resulting SrcOps to get final list.
@ -426,14 +457,14 @@ public class OutputModelController {
public void setRoot(OutputModelObject root) { this.root = root; }
public RuleFunction getCurrentRuleFunction() {
if ( currentRule.size()>0 ) return currentRule.peek();
if ( !currentRule.isEmpty() ) return currentRule.peek();
return null;
}
public void pushCurrentRule(RuleFunction r) { currentRule.push(r); }
public RuleFunction popCurrentRule() {
if ( currentRule.size()>0 ) return currentRule.pop();
if ( !currentRule.isEmpty() ) return currentRule.pop();
return null;
}

View File

@ -30,14 +30,21 @@
package org.antlr.v4.codegen;
import org.antlr.v4.Tool;
import org.antlr.v4.codegen.model.ModelElement;
import org.antlr.v4.codegen.model.OutputModelObject;
import org.antlr.v4.tool.ErrorType;
import org.stringtemplate.v4.*;
import org.stringtemplate.v4.ST;
import org.stringtemplate.v4.STGroup;
import org.stringtemplate.v4.compiler.FormalArgument;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.*;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/** Convert an output model tree to template hierarchy by walking
* the output model. Each output model object has a corresponding template
@ -94,13 +101,24 @@ public class OutputModelWalker {
st.add(modelArgName, omo);
// COMPUTE STs FOR EACH NESTED MODEL OBJECT MARKED WITH @ModelElement AND MAKE ST ATTRIBUTE
Set<String> usedFieldNames = new HashSet<String>();
Field fields[] = cl.getFields();
for (Field fi : fields) {
Annotation[] annotations = fi.getAnnotations();
if ( annotations.length==0 ) continue;
ModelElement annotation = fi.getAnnotation(ModelElement.class);
if (annotation == null) {
continue;
}
String fieldName = fi.getName();
if (!usedFieldNames.add(fieldName)) {
tool.errMgr.toolError(ErrorType.INTERNAL_ERROR, "Model object " + omo.getClass().getSimpleName() + " has multiple fields named '" + fieldName + "'");
continue;
}
// Just don't set @ModelElement fields w/o formal arg in target ST
if ( formalArgs.get(fieldName)==null ) continue;
try {
Object o = fi.get(omo);
if ( o instanceof OutputModelObject ) { // SINGLE MODEL OBJECT?

View File

@ -31,9 +31,10 @@ package org.antlr.v4.codegen;
import org.antlr.v4.codegen.model.RuleFunction;
import org.antlr.v4.misc.Utils;
import org.antlr.v4.parse.ANTLRParser;
import org.antlr.v4.runtime.*;
import org.antlr.v4.tool.*;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.tool.Grammar;
import org.antlr.v4.tool.Rule;
import org.antlr.v4.tool.ast.GrammarAST;
import org.stringtemplate.v4.ST;
@ -91,20 +92,12 @@ public class Target {
* Literals without associated names are converted to the string equivalent
* of their integer values. Used to generate x==ID and x==34 type comparisons
* etc... Essentially we are looking for the most obvious way to refer
* to a token type in the generated code. If in the lexer, return the
* char literal translated to the target language. For example, ttype=10
* will yield '\n' from the getTokenDisplayName method. That must
* be converted to the target languages literals. For most C-derived
* languages no translation is needed.
* to a token type in the generated code.
*/
public String getTokenTypeAsTargetLabel(Grammar g, int ttype) {
if ( g.getType() == ANTLRParser.LEXER ) {
// String name = g.getTokenDisplayName(ttype);
// return getTargetCharLiteralFromANTLRCharLiteral(this,name);
}
String name = g.getTokenDisplayName(ttype);
// If name is a literal, return the token type instead
if ( name.charAt(0)=='\'' ) {
if ( name==null || name.charAt(0)=='\'' ) {
return String.valueOf(ttype);
}
return name;

View File

@ -1,3 +1,31 @@
/*
[The "BSD license"]
Copyright (c) 2012 Terence Parr
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.codegen.model;
import org.antlr.v4.codegen.OutputModelFactory;

View File

@ -1,3 +1,31 @@
/*
[The "BSD license"]
Copyright (c) 2012 Terence Parr
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.codegen.model;
import org.antlr.v4.codegen.OutputModelFactory;

View File

@ -1,3 +1,31 @@
/*
[The "BSD license"]
Copyright (c) 2012 Terence Parr
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.codegen.model;
import org.antlr.v4.codegen.OutputModelFactory;

View File

@ -1,3 +1,31 @@
/*
[The "BSD license"]
Copyright (c) 2012 Terence Parr
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.codegen.model;
import org.antlr.v4.codegen.OutputModelFactory;

View File

@ -29,7 +29,8 @@
package org.antlr.v4.codegen.model;
import org.antlr.v4.codegen.*;
import org.antlr.v4.codegen.CodeGenerator;
import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.runtime.atn.PlusBlockStartState;
import org.antlr.v4.runtime.misc.IntervalSet;
import org.antlr.v4.tool.Grammar;
@ -46,7 +47,6 @@ public class LL1PlusBlock extends LL1Loop {
public String loopCounterVar;
public String[] exitLook;
@ModelElement public SrcOp loopExpr;
@ModelElement public ThrowNoViableAlt error;
public LL1PlusBlock(OutputModelFactory factory, GrammarAST plusRoot, List<CodeBlockForAlt> alts) {

View File

@ -1,3 +1,31 @@
/*
[The "BSD license"]
Copyright (c) 2012 Terence Parr
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.codegen.model;
import org.antlr.v4.codegen.OutputModelFactory;

View File

@ -1,3 +1,31 @@
/*
[The "BSD license"]
Copyright (c) 2012 Terence Parr
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.codegen.model;
import org.antlr.v4.codegen.OutputModelFactory;

View File

@ -37,7 +37,7 @@ public abstract class OutputModelObject {
public OutputModelFactory factory;
public GrammarAST ast;
public OutputModelObject() {;}
public OutputModelObject() {}
public OutputModelObject(OutputModelFactory factory) { this(factory, null); }

View File

@ -90,7 +90,7 @@ public class RuleFunction extends OutputModelObject {
super(factory);
this.name = r.name;
this.rule = r;
if ( r.modifiers!=null && r.modifiers.size()>0 ) {
if ( r.modifiers!=null && !r.modifiers.isEmpty() ) {
this.modifiers = new ArrayList<String>();
for (GrammarAST t : r.modifiers) modifiers.add(t.getText());
}

View File

@ -1,3 +1,31 @@
/*
[The "BSD license"]
Copyright (c) 2012 Terence Parr
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.codegen.model;
import org.antlr.v4.codegen.OutputModelFactory;

View File

@ -1,3 +1,31 @@
/*
[The "BSD license"]
Copyright (c) 2012 Terence Parr
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.codegen.model;
import org.antlr.v4.codegen.OutputModelFactory;

View File

@ -1,3 +1,32 @@
/*
[The "BSD license"]
Copyright (c) 2012 Terence Parr
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.codegen.model.chunk;
import org.antlr.v4.codegen.model.decl.StructDecl;

View File

@ -30,8 +30,12 @@
package org.antlr.v4.codegen.model.decl;
import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.codegen.model.*;
import org.antlr.v4.tool.*;
import org.antlr.v4.codegen.model.DispatchMethod;
import org.antlr.v4.codegen.model.ListenerDispatchMethod;
import org.antlr.v4.codegen.model.ParseListenerDispatchMethod;
import org.antlr.v4.codegen.model.VisitorDispatchMethod;
import org.antlr.v4.tool.LeftRecursiveRule;
import org.antlr.v4.tool.Rule;
import java.util.ArrayList;
@ -75,10 +79,8 @@ public class AltLabelStructDecl extends StructDecl {
@Override
public boolean equals(Object obj) {
if ( obj == this ) return true;
if ( obj.hashCode() != this.hashCode() ) return false;
if ( obj instanceof AltLabelStructDecl ) {
return name.equals(((AltLabelStructDecl)obj).name);
}
return false;
if (!(obj instanceof AltLabelStructDecl)) return false;
return name.equals(((AltLabelStructDecl)obj).name);
}
}

View File

@ -1,3 +1,32 @@
/*
[The "BSD license"]
Copyright (c) 2012 Terence Parr
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.codegen.model.decl;
import org.antlr.v4.codegen.OutputModelFactory;
@ -23,11 +52,9 @@ public abstract class ContextGetterDecl extends Decl {
*/
@Override
public boolean equals(Object obj) {
if ( obj==null ) return false;
if ( this==obj ) return true;
// A() and label A are different
if ( !(obj instanceof ContextGetterDecl) ) return false;
if ( this==obj ) return true;
if ( this.hashCode() != obj.hashCode() ) return false;
return
name.equals(((Decl) obj).name) &&
getArgType().equals(((ContextGetterDecl) obj).getArgType());

View File

@ -1,8 +1,37 @@
/*
[The "BSD license"]
Copyright (c) 2012 Terence Parr
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.codegen.model.decl;
import org.antlr.v4.codegen.OutputModelFactory;
/** public XContext X() { } */
/** {@code public XContext X() { }} */
public class ContextRuleGetterDecl extends ContextGetterDecl {
public String ctxName;
public ContextRuleGetterDecl(OutputModelFactory factory, String name, String ctxName) {

View File

@ -1,9 +1,38 @@
/*
[The "BSD license"]
Copyright (c) 2012 Terence Parr
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.codegen.model.decl;
import org.antlr.v4.codegen.OutputModelFactory;
/** public List<XContext> X() { }
* public XContext X(int i) { }
/** {@code public List<XContext> X() { }
* public XContext X(int i) { }}
*/
public class ContextRuleListGetterDecl extends ContextGetterDecl {
public String ctxName;

View File

@ -1,3 +1,32 @@
/*
[The "BSD license"]
Copyright (c) 2012 Terence Parr
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.codegen.model.decl;
import org.antlr.v4.codegen.OutputModelFactory;

View File

@ -1,8 +1,37 @@
/*
[The "BSD license"]
Copyright (c) 2012 Terence Parr
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.codegen.model.decl;
import org.antlr.v4.codegen.OutputModelFactory;
/** public Token X() { } */
/** {@code public Token X() { }} */
public class ContextTokenGetterDecl extends ContextGetterDecl {
public ContextTokenGetterDecl(OutputModelFactory factory, String name) {
super(factory, name);

View File

@ -1,9 +1,38 @@
/*
[The "BSD license"]
Copyright (c) 2012 Terence Parr
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.codegen.model.decl;
import org.antlr.v4.codegen.OutputModelFactory;
/** public List<Token> X() { }
* public Token X(int i) { }
/** {@code public List<Token> X() { }
* public Token X(int i) { }}
*/
public class ContextTokenListGetterDecl extends ContextGetterDecl {
public ContextTokenListGetterDecl(OutputModelFactory factory, String name) {

View File

@ -1,3 +1,32 @@
/*
[The "BSD license"]
Copyright (c) 2012 Terence Parr
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.codegen.model.decl;
import org.antlr.v4.codegen.OutputModelFactory;

View File

@ -57,11 +57,10 @@ public class Decl extends SrcOp {
/** If same name, can't redefine, unless it's a getter */
@Override
public boolean equals(Object obj) {
if ( obj==null ) return false;
if ( this==obj ) return true;
if ( !(obj instanceof Decl) ) return false;
// A() and label A are different
if ( obj instanceof ContextGetterDecl ) return false;
if ( this==obj ) return true;
if ( this.hashCode() != obj.hashCode() ) return false;
return name.equals(((Decl) obj).name);
}
}

View File

@ -115,5 +115,5 @@ public class StructDecl extends Decl {
extensionMembers.add(member);
}
public boolean isEmpty() { return attrs.size()==0; }
public boolean isEmpty() { return attrs.isEmpty(); }
}

View File

@ -1,9 +1,38 @@
/*
[The "BSD license"]
Copyright (c) 2012 Terence Parr
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.misc;
import java.util.Hashtable;
import java.util.HashMap;
/** Count how many of each key we have; not thread safe */
public class FrequencySet<T> extends Hashtable<T, MutableInt> {
public class FrequencySet<T> extends HashMap<T, MutableInt> {
public int count(T key) {
MutableInt value = get(key);
if (value == null) return 0;

View File

@ -1,3 +1,32 @@
/*
[The "BSD license"]
Copyright (c) 2012 Terence Parr
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.misc;
public class MutableInt extends Number implements Comparable<Number> {

View File

@ -106,7 +106,7 @@ alternative returns [ATNFactory.Handle p]
lexerCommands returns [ATNFactory.Handle p]
@init {StringBuilder cmds = new StringBuilder();}
: (c=lexerCommand {cmds.append($c.cmd+" ");})+
: (c=lexerCommand {cmds.append($c.cmd).append(' ');})+
{
$p = factory.action(cmds.toString());
}

View File

@ -82,7 +82,7 @@ TEXT
@after {delegate.text(buf.toString());}
: ( c=~('\\'| '$') {buf.append((char)$c);}
| '\\$' {buf.append("$");}
| '\\' c=~('$') {buf.append("\\"+(char)$c);}
| '\\' c=~('$') {buf.append('\\').append((char)$c);}
)+
;

View File

@ -39,7 +39,7 @@ import org.antlr.v4.tool.ast.TerminalAST;
public class GrammarASTAdaptor extends CommonTreeAdaptor {
org.antlr.runtime.CharStream input; // where we can find chars ref'd by tokens in tree
public GrammarASTAdaptor() { ; }
public GrammarASTAdaptor() { }
public GrammarASTAdaptor(org.antlr.runtime.CharStream input) { this.input = input; }
@Override
@ -50,7 +50,7 @@ public class GrammarASTAdaptor extends CommonTreeAdaptor {
@Override
/** Make sure even imaginary nodes know the input stream */
public Object create(int tokenType, String text) {
GrammarAST t = null;
GrammarAST t;
if ( tokenType==ANTLRParser.RULE ) {
// needed by TreeWizard to make RULE tree
t = new RuleAST(new CommonToken(tokenType, text));

View File

@ -30,12 +30,18 @@
package org.antlr.v4.parse;
import org.antlr.v4.Tool;
import org.antlr.v4.codegen.CodeGenerator;
import org.antlr.v4.tool.ErrorType;
import java.io.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import org.antlr.v4.codegen.CodeGenerator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/** */
public class TokenVocabParser {
@ -53,69 +59,31 @@ public class TokenVocabParser {
int maxTokenType = -1;
File fullFile = getImportedVocabFile();
try {
Pattern tokenDefPattern = Pattern.compile("([^\n]+?)[ \\t]*?=[ \\t]*?([0-9]+)");
FileReader fr = new FileReader(fullFile);
BufferedReader br = new BufferedReader(fr);
StreamTokenizer tokenizer = new StreamTokenizer(br);
tokenizer.parseNumbers();
tokenizer.wordChars('_', '_');
tokenizer.eolIsSignificant(true);
tokenizer.slashSlashComments(true);
tokenizer.slashStarComments(true);
tokenizer.ordinaryChar('=');
tokenizer.quoteChar('\'');
tokenizer.whitespaceChars(' ',' ');
tokenizer.whitespaceChars('\t','\t');
String tokenDef = br.readLine();
int lineNum = 1;
int token = tokenizer.nextToken();
while (token != StreamTokenizer.TT_EOF) {
String tokenID;
if ( token == StreamTokenizer.TT_WORD ) {
tokenID = tokenizer.sval;
}
else if ( token == '\'' ) {
tokenID = "'"+tokenizer.sval+"'";
while ( tokenDef!=null ) {
Matcher matcher = tokenDefPattern.matcher(tokenDef);
if ( matcher.find() ) {
String tokenID = matcher.group(1);
String tokenTypeS = matcher.group(2);
int tokenType = Integer.valueOf(tokenTypeS);
tool.log("grammar", "import "+tokenID+"="+tokenType);
tokens.put(tokenID, tokenType);
maxTokenType = Math.max(maxTokenType,tokenType);
lineNum++;
}
else {
tool.errMgr.toolError(ErrorType.TOKENS_FILE_SYNTAX_ERROR,
vocabName + CodeGenerator.VOCAB_FILE_EXTENSION,
lineNum);
while ( tokenizer.nextToken() != StreamTokenizer.TT_EOL ) {;}
token = tokenizer.nextToken();
continue;
if ( tokenDef.length()>0 ) { // ignore blank lines
tool.errMgr.toolError(ErrorType.TOKENS_FILE_SYNTAX_ERROR,
vocabName + CodeGenerator.VOCAB_FILE_EXTENSION,
" bad token def: "+tokenDef,
lineNum);
}
}
token = tokenizer.nextToken();
if ( token != '=' ) {
tool.errMgr.toolError(ErrorType.TOKENS_FILE_SYNTAX_ERROR,
vocabName+CodeGenerator.VOCAB_FILE_EXTENSION,
lineNum);
while ( tokenizer.nextToken() != StreamTokenizer.TT_EOL ) {;}
token = tokenizer.nextToken();
continue;
}
token = tokenizer.nextToken(); // skip '='
if ( token != StreamTokenizer.TT_NUMBER ) {
tool.errMgr.toolError(ErrorType.TOKENS_FILE_SYNTAX_ERROR,
vocabName+CodeGenerator.VOCAB_FILE_EXTENSION,
lineNum);
while ( tokenizer.nextToken() != StreamTokenizer.TT_EOL ) {;}
token = tokenizer.nextToken();
continue;
}
int tokenType = (int)tokenizer.nval;
token = tokenizer.nextToken();
tool.log("grammar", "import "+tokenID+"="+tokenType);
tokens.put(tokenID, tokenType);
maxTokenType = Math.max(maxTokenType,tokenType);
lineNum++;
if ( token != StreamTokenizer.TT_EOL ) {
tool.errMgr.toolError(ErrorType.TOKENS_FILE_SYNTAX_ERROR,
vocabName+CodeGenerator.VOCAB_FILE_EXTENSION,
lineNum);
while ( tokenizer.nextToken() != StreamTokenizer.TT_EOL ) {;}
token = tokenizer.nextToken();
continue;
}
token = tokenizer.nextToken(); // skip newline
tokenDef = br.readLine();
}
br.close();
}
@ -159,7 +127,6 @@ public class TokenVocabParser {
// to look for it in the output directory which is where .tokens
// files are generated (in the base, not relative to the input
// location.)
//
f = new File(tool.outputDirectory, vocabName + CodeGenerator.VOCAB_FILE_EXTENSION);
return f;
}

View File

@ -29,7 +29,10 @@
package org.antlr.v4.parse;
import org.antlr.runtime.*;
import org.antlr.runtime.NoViableAltException;
import org.antlr.runtime.Parser;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.TokenStream;
import org.antlr.v4.Tool;
import org.antlr.v4.tool.ErrorType;
@ -49,7 +52,7 @@ public class ToolANTLRParser extends ANTLRParser {
RecognitionException e)
{
String msg = getParserErrorMessage(this, e);
if ( paraphrases.size()>0 ) {
if ( !paraphrases.isEmpty() ) {
String paraphrase = (String)paraphrases.peek();
msg = msg+" while "+paraphrase;
}
@ -59,7 +62,7 @@ public class ToolANTLRParser extends ANTLRParser {
}
public String getParserErrorMessage(Parser parser, RecognitionException e) {
String msg = null;
String msg;
if ( e instanceof NoViableAltException) {
String name = parser.getTokenErrorDisplay(e.token);
msg = name+" came as a complete surprise to me";

View File

@ -29,13 +29,14 @@
package org.antlr.v4.parse;
import org.antlr.runtime.*;
import org.antlr.runtime.IntStream;
import org.antlr.runtime.RecognitionException;
/** */
public class v4ParserException extends RecognitionException {
public String msg;
/** Used for remote debugger deserialization */
public v4ParserException() {;}
public v4ParserException() {}
public v4ParserException(String msg, IntStream input) {
super(input);

View File

@ -107,11 +107,11 @@ public class ActionSniffer extends BlankActionSplitterListener {
public void trackRef(Token x) {
List<TerminalAST> xRefs = alt.tokenRefs.get(x.getText());
if ( alt!=null && xRefs!=null ) {
if ( xRefs!=null ) {
alt.tokenRefsInActions.map(x.getText(), node);
}
List<GrammarAST> rRefs = alt.ruleRefs.get(x.getText());
if ( alt!=null && rRefs!=null ) {
if ( rRefs!=null ) {
alt.ruleRefsInActions.map(x.getText(), node);
}
}

View File

@ -33,7 +33,13 @@ import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.Token;
import org.antlr.v4.parse.ActionSplitter;
import org.antlr.v4.parse.ActionSplitterListener;
import org.antlr.v4.tool.*;
import org.antlr.v4.tool.Alternative;
import org.antlr.v4.tool.ErrorManager;
import org.antlr.v4.tool.ErrorType;
import org.antlr.v4.tool.Grammar;
import org.antlr.v4.tool.LabelElementPair;
import org.antlr.v4.tool.LabelType;
import org.antlr.v4.tool.Rule;
import org.antlr.v4.tool.ast.ActionAST;
import java.util.List;
@ -168,7 +174,7 @@ public class AttributeChecks implements ActionSplitterListener {
errMgr.toolError(ErrorType.UNDEFINED_RULE_IN_NONLOCAL_REF,
x.getText(), y.getText());
}
if ( r.resolveToAttribute(y.getText(), null)==null ) {
else if ( r.resolveToAttribute(y.getText(), null)==null ) {
errMgr.grammarError(ErrorType.UNKNOWN_RULE_ATTRIBUTE,
g.fileName, y, y.getText(), x.getText(), expr);
@ -182,7 +188,7 @@ public class AttributeChecks implements ActionSplitterListener {
errMgr.toolError(ErrorType.UNDEFINED_RULE_IN_NONLOCAL_REF,
x.getText(), y.getText());
}
if ( r.resolveToAttribute(y.getText(), null)==null ) {
else if ( r.resolveToAttribute(y.getText(), null)==null ) {
errMgr.grammarError(ErrorType.UNKNOWN_RULE_ATTRIBUTE,
g.fileName, y, y.getText(), x.getText(), expr);

View File

@ -30,13 +30,23 @@
package org.antlr.v4.semantics;
import org.antlr.v4.analysis.LeftRecursiveRuleAnalyzer;
import org.antlr.v4.misc.*;
import org.antlr.v4.parse.*;
import org.antlr.v4.tool.*;
import org.antlr.v4.tool.ast.*;
import org.antlr.v4.misc.OrderedHashMap;
import org.antlr.v4.misc.Utils;
import org.antlr.v4.parse.GrammarTreeVisitor;
import org.antlr.v4.parse.ScopeParser;
import org.antlr.v4.tool.AttributeDict;
import org.antlr.v4.tool.Grammar;
import org.antlr.v4.tool.LeftRecursiveRule;
import org.antlr.v4.tool.Rule;
import org.antlr.v4.tool.ast.ActionAST;
import org.antlr.v4.tool.ast.AltAST;
import org.antlr.v4.tool.ast.GrammarAST;
import org.antlr.v4.tool.ast.RuleAST;
import org.stringtemplate.v4.misc.MultiMap;
import java.util.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class RuleCollector extends GrammarTreeVisitor {
/** which grammar are we checking */
@ -62,7 +72,7 @@ public class RuleCollector extends GrammarTreeVisitor {
GrammarAST block)
{
int numAlts = block.getChildCount();
Rule r = null;
Rule r;
if ( LeftRecursiveRuleAnalyzer.hasImmediateRecursiveRuleRefs(rule, ID.getText()) ) {
r = new LeftRecursiveRule(g, ID.getText(), rule);
}
@ -115,7 +125,7 @@ public class RuleCollector extends GrammarTreeVisitor {
int numAlts = block.getChildCount();
Rule r = new Rule(g, ID.getText(), rule, numAlts);
r.mode = currentModeName;
if ( modifiers.size()>0 ) r.modifiers = modifiers;
if ( !modifiers.isEmpty() ) r.modifiers = modifiers;
rules.put(r.name, r);
}
}

View File

@ -82,7 +82,7 @@ public class SemanticPipeline {
basics.process();
// don't continue if we get errors in this basic check
if ( false ) return;
//if ( false ) return;
// TRANSFORM LEFT-RECURSIVE RULES
LeftRecursiveRuleTransformer lrtrans =

View File

@ -30,10 +30,21 @@
package org.antlr.v4.semantics;
import org.antlr.v4.parse.ANTLRParser;
import org.antlr.v4.tool.*;
import org.antlr.v4.tool.Alternative;
import org.antlr.v4.tool.ErrorManager;
import org.antlr.v4.tool.ErrorType;
import org.antlr.v4.tool.Grammar;
import org.antlr.v4.tool.LabelElementPair;
import org.antlr.v4.tool.Rule;
import org.antlr.v4.tool.ast.GrammarAST;
import java.util.*;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/** Check for symbol problems; no side-effects. Inefficient to walk rules
* and such multiple times, but I like isolating all error checking outside
@ -103,8 +114,8 @@ public class SymbolChecks {
public void checkActionRedefinitions(List<GrammarAST> actions) {
if ( actions==null ) return;
String scope = g.getDefaultActionScope();
String name = null;
GrammarAST nameNode = null;
String name;
GrammarAST nameNode;
for (GrammarAST ampersandAST : actions) {
nameNode = (GrammarAST)ampersandAST.getChild(0);
if ( ampersandAST.getChildCount()==2 ) {
@ -280,7 +291,7 @@ public class SymbolChecks {
g.fileName, ref.token, ruleName);
}
GrammarAST arg = (GrammarAST)ref.getChild(0);
if ( arg!=null && r.args==null ) {
if ( arg!=null && (r==null || r.args==null) ) {
errMgr.grammarError(ErrorType.RULE_HAS_NO_ARGS,
g.fileName, ref.token, ruleName);

View File

@ -48,7 +48,7 @@ public class Attribute {
/** Who contains us? */
public AttributeDict dict;
public Attribute() {;}
public Attribute() {}
public Attribute(String name) { this(name,null); }

View File

@ -30,14 +30,38 @@
package org.antlr.v4.tool;
import org.antlr.v4.misc.Utils;
import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.atn.ATNConfig;
import org.antlr.v4.runtime.atn.ATNState;
import org.antlr.v4.runtime.atn.ActionTransition;
import org.antlr.v4.runtime.atn.AtomTransition;
import org.antlr.v4.runtime.atn.BlockEndState;
import org.antlr.v4.runtime.atn.BlockStartState;
import org.antlr.v4.runtime.atn.DecisionState;
import org.antlr.v4.runtime.atn.NotSetTransition;
import org.antlr.v4.runtime.atn.PlusBlockStartState;
import org.antlr.v4.runtime.atn.PlusLoopbackState;
import org.antlr.v4.runtime.atn.PredicateTransition;
import org.antlr.v4.runtime.atn.RangeTransition;
import org.antlr.v4.runtime.atn.RuleStopState;
import org.antlr.v4.runtime.atn.RuleTransition;
import org.antlr.v4.runtime.atn.SetTransition;
import org.antlr.v4.runtime.atn.StarBlockStartState;
import org.antlr.v4.runtime.atn.StarLoopEntryState;
import org.antlr.v4.runtime.atn.StarLoopbackState;
import org.antlr.v4.runtime.atn.Transition;
import org.antlr.v4.runtime.dfa.DFA;
import org.antlr.v4.runtime.dfa.DFAState;
import org.stringtemplate.v4.ST;
import org.stringtemplate.v4.STGroup;
import org.stringtemplate.v4.STGroupDir;
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
/** The DOT (part of graphviz) generation aspect. */
public class DOTGenerator {
@ -187,7 +211,7 @@ public class DOTGenerator {
List<ATNState> work = new LinkedList<ATNState>();
work.add(startState);
while ( work.size()>0 ) {
while ( !work.isEmpty() ) {
ATNState s = work.get(0);
if ( markedStates.contains(s) ) { work.remove(0); continue; }
markedStates.add(s);

View File

@ -274,7 +274,7 @@ public class ErrorManager {
format = new STGroupFile(fileName, "UTF-8");
format.load();
if ( initSTListener.errors.size()>0 ) {
if ( !initSTListener.errors.isEmpty() ) {
rawError("ANTLR installation corrupted; can't load messages format file:\n"+
initSTListener.toString());
panic();

View File

@ -385,7 +385,7 @@ public class Grammar implements AttributeResolver {
List<Grammar> grammarsFromRootToMe = getOutermostGrammar().getGrammarAncestors();
String qualifiedName = name;
if ( grammarsFromRootToMe!=null ) {
StringBuffer buf = new StringBuffer();
StringBuilder buf = new StringBuilder();
for (Grammar g : grammarsFromRootToMe) {
buf.append(g.name);
buf.append('_');
@ -420,7 +420,7 @@ public class Grammar implements AttributeResolver {
}
public int getTokenType(String token) {
Integer I = null;
Integer I;
if ( token.charAt(0)=='\'') {
I = stringLiteralToTypeMap.get(token);
}
@ -437,7 +437,7 @@ public class Grammar implements AttributeResolver {
* char vocabulary, compute an ANTLR-valid (possibly escaped) char literal.
*/
public String getTokenDisplayName(int ttype) {
String tokenName = null;
String tokenName;
// inside any target's char range and is lexer grammar?
if ( isLexer() &&
ttype >= Lexer.MIN_CHAR_VALUE && ttype <= Lexer.MAX_CHAR_VALUE )
@ -742,51 +742,56 @@ public class Grammar implements AttributeResolver {
}
public static Map<String,String> getStringLiteralAliasesFromLexerRules(GrammarRootAST ast) {
String[] patterns = {
"(RULE %name:TOKEN_REF (BLOCK (ALT %lit:STRING_LITERAL)))",
"(RULE %name:TOKEN_REF (BLOCK (ALT %lit:STRING_LITERAL ACTION)))",
"(RULE %name:TOKEN_REF (BLOCK (ALT %lit:STRING_LITERAL SEMPRED)))",
"(RULE %name:TOKEN_REF (BLOCK (LEXER_ALT_ACTION (ALT %lit:STRING_LITERAL) .)))",
"(RULE %name:TOKEN_REF (BLOCK (LEXER_ALT_ACTION (ALT %lit:STRING_LITERAL) . .)))",
"(RULE %name:TOKEN_REF (BLOCK (LEXER_ALT_ACTION (ALT %lit:STRING_LITERAL) (LEXER_ACTION_CALL . .))))",
"(RULE %name:TOKEN_REF (BLOCK (LEXER_ALT_ACTION (ALT %lit:STRING_LITERAL) . (LEXER_ACTION_CALL . .))))",
"(RULE %name:TOKEN_REF (BLOCK (LEXER_ALT_ACTION (ALT %lit:STRING_LITERAL) (LEXER_ACTION_CALL . .) .)))",
// TODO: allow doc comment in there
};
GrammarASTAdaptor adaptor = new GrammarASTAdaptor(ast.token.getInputStream());
TreeWizard wiz = new TreeWizard(adaptor,ANTLRParser.tokenNames);
Map<String,String> lexerRuleToStringLiteral = new HashMap<String,String>();
List<GrammarAST> ruleNodes = ast.getNodesWithType(ANTLRParser.RULE);
if ( ruleNodes==null || ruleNodes.size()==0 ) return null;
if ( ruleNodes==null || ruleNodes.isEmpty() ) return null;
for (GrammarAST r : ruleNodes) {
for (GrammarAST r : ruleNodes) {
//tool.log("grammar", r.toStringTree());
// System.out.println("chk: "+r.toStringTree());
Tree name = r.getChild(0);
if ( name.getType()==ANTLRParser.TOKEN_REF ) {
Map nodes = new HashMap();
boolean isLitRule =
wiz.parse(r, "(RULE %name:TOKEN_REF (BLOCK (ALT %lit:STRING_LITERAL)))", nodes);
if ( isLitRule ) {
GrammarAST litNode = (GrammarAST)nodes.get("lit");
GrammarAST nameNode = (GrammarAST)nodes.get("name");
lexerRuleToStringLiteral.put(litNode.getText(), nameNode.getText());
continue;
if ( name.getType()==ANTLRParser.TOKEN_REF ) {
// check rule against patterns
boolean isLitRule;
for (String pattern : patterns) {
isLitRule =
defAlias(r, pattern, wiz, lexerRuleToStringLiteral);
if ( isLitRule ) break;
}
// TODO: allow doc comment in there
nodes = new HashMap();
// try with action in there
isLitRule =
wiz.parse(r, "(RULE %name:TOKEN_REF (BLOCK (ALT %lit:STRING_LITERAL ACTION)))", nodes);
if ( isLitRule ) {
GrammarAST litNode = (GrammarAST)nodes.get("lit");
GrammarAST nameNode = (GrammarAST)nodes.get("name");
lexerRuleToStringLiteral.put(litNode.getText(), nameNode.getText());
continue;
}
nodes = new HashMap();
// try with pred in there
isLitRule =
wiz.parse(r, "(RULE %name:TOKEN_REF (BLOCK (ALT %lit:STRING_LITERAL SEMPRED)))", nodes);
if ( isLitRule ) {
GrammarAST litNode = (GrammarAST)nodes.get("lit");
GrammarAST nameNode = (GrammarAST)nodes.get("name");
lexerRuleToStringLiteral.put(litNode.getText(), nameNode.getText());
}
}
}
// if ( !isLitRule ) System.out.println("no pattern matched");
}
}
return lexerRuleToStringLiteral;
}
protected static boolean defAlias(GrammarAST r, String pattern,
TreeWizard wiz,
Map<String, String> lexerRuleToStringLiteral)
{
HashMap<String, Object> nodes = new HashMap<String, Object>();
if ( wiz.parse(r, pattern, nodes) ) {
GrammarAST litNode = (GrammarAST)nodes.get("lit");
GrammarAST nameNode = (GrammarAST)nodes.get("name");
lexerRuleToStringLiteral.put(litNode.getText(), nameNode.getText());
return true;
}
return false;
}
public Set<String> getStringLiterals() {
final Set<String> strings = new HashSet<String>();
GrammarTreeVisitor collector = new GrammarTreeVisitor() {

View File

@ -78,7 +78,7 @@ public class LeftRecursiveRule extends Rule {
LeftRecursiveRuleAltInfo altInfo = recOpAlts.getElement(i);
if ( altInfo.altLabel==null ) alts.add(altInfo.originalAltAST);
}
if ( alts.size()==0 ) return null;
if ( alts.isEmpty() ) return null;
return alts;
}
@ -104,7 +104,7 @@ public class LeftRecursiveRule extends Rule {
altInfo.altLabel));
}
}
if ( labels.size()==0 ) return null;
if ( labels.isEmpty() ) return null;
return labels;
}
}

View File

@ -184,7 +184,7 @@ public class Rule implements AttributeResolver {
for (int i=1; i<=numberOfAlts; i++) {
refs.addAll(alt[i].labelDefs.keySet());
}
if ( refs.size()==0 ) return null;
if ( refs.isEmpty() ) return null;
return refs;
}
@ -219,7 +219,7 @@ public class Rule implements AttributeResolver {
labels.add(new Triple<Integer,AltAST,String>(i,alt[i].ast,altLabel.getText()));
}
}
if ( labels.size()==0 ) return null;
if ( labels.isEmpty() ) return null;
return labels;
}
@ -229,7 +229,7 @@ public class Rule implements AttributeResolver {
GrammarAST altLabel = alt[i].ast.altLabel;
if ( altLabel==null ) alts.add(alt[i].ast);
}
if ( alts.size()==0 ) return null;
if ( alts.isEmpty() ) return null;
return alts;
}
@ -332,15 +332,23 @@ public class Rule implements AttributeResolver {
@Override
public boolean equals(Object obj) {
return this==obj || name.equals(((Rule)obj).name);
if (this == obj) {
return true;
}
if (!(obj instanceof Rule)) {
return false;
}
return name.equals(((Rule)obj).name);
}
@Override
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append("Rule{name="+name);
if ( args!=null ) buf.append(", args=" + args);
if ( retvals!=null ) buf.append(", retvals=" + retvals);
buf.append("Rule{name=").append(name);
if ( args!=null ) buf.append(", args=").append(args);
if ( retvals!=null ) buf.append(", retvals=").append(retvals);
buf.append("}");
return buf.toString();
}

View File

@ -100,7 +100,7 @@ public class GrammarAST extends CommonTree {
List<GrammarAST> work = new LinkedList<GrammarAST>();
work.add(this);
GrammarAST t;
while ( work.size()>0 ) {
while ( !work.isEmpty() ) {
t = work.remove(0);
if ( types.contains(t.getType()) ) nodes.add(t);
if ( t.children!=null ) work.addAll((Collection)t.children);

View File

@ -1,3 +1,32 @@
/*
[The "BSD license"]
Copyright (c) 2012 Terence Parr
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.tool.ast;
/** A simple visitor, based upon the classic double dispatch method,

View File

@ -1,3 +1,32 @@
/*
[The "BSD license"]
Copyright (c) 2012 Terence Parr
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.tool.ast;
import org.antlr.runtime.Token;

View File

@ -1,3 +1,32 @@
/*
[The "BSD license"]
Copyright (c) 2012 Terence Parr
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.tool.ast;
import org.antlr.runtime.Token;

Some files were not shown because too many files have changed in this diff Show More