Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ Bundle-Version: 1.0.0
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Export-Package: com.github.jhoenicke.javacup.runtime
Bundle-ClassPath: .
Automatic-Module-Name: JavaCup

5 changes: 2 additions & 3 deletions build.properties
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
bin.includes = META-INF/,\
java-cup-12joho.jar,\
ant.jar,\
.
output.. = bin/
jars.extra.classpath = ant.jar
jars.extra.classpath = ../ant.jar

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these changes intended?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes/no, in fact I move the ant.jat outside the projet as I have to download it separatly. Unfortunatly, I have to update the build.properties (but may be it is environnement dependant and should not be part of a git.

source.. = src/
jre.compilation.profile = JavaSE-1.8
9 changes: 6 additions & 3 deletions build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<property name="cup" location="cup" />

<property name="package" value="com/github/jhoenicke/javacup" />
<property name="version" value="1.2"/>
<property name="version" value="1.3"/>
<property name="jar" value="jh-javacup-${version}"/>
<property name="runtimejar" value="${jar}-runtime"/>

Expand Down Expand Up @@ -56,12 +56,12 @@
<fileset dir="${src}">
<exclude name="${package}/Parser.java"/>
<exclude name="${package}/Lexer.java"/>
<exclude name="${package}/sym.java"/>
<exclude name="${package}/Sym.java"/>
</fileset>
</copy>
<java fork="true" classpath="${bootstrap}" classname="com.github.jhoenicke.javacup.Main">
<arg value="-destdir"/>
<arg value="${java}/${package}"/>
<arg value="${java}"/>
<arg value="${cup}/parser.cup"/>
</java>
<jflex file="${flex}/Lexer.jflex" destdir="${java}" />
Expand All @@ -80,6 +80,9 @@
<jar jarfile="${dist}/${runtimejar}.jar" basedir="${classes}"
includes="${package}/runtime/*">
</jar>
<zip destfile="${dist}/${runtimejar}.zip" basedir="."
includes="src/${package}/runtime/*">
</zip>
</target>

<target name="test" depends="dist">
Expand Down
48 changes: 22 additions & 26 deletions cup/parser.cup
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,6 @@ action code {:
/* if it wasn't declared of the right type, emit a message */
if (!(sym instanceof terminal))
{
if (ErrorManager.getManager().getErrorCount() == 0)
ErrorManager.getManager().emit_warning("Terminal \"" + id +
"\" has not been declared", location);
return null;
Expand All @@ -154,7 +153,6 @@ action code {:
/* if it wasn't declared of the right type, emit a message */
if (!(sym instanceof non_terminal))
{
if (ErrorManager.getManager().getErrorCount() == 0)
ErrorManager.getManager().emit_warning("Non-terminal \"" + id +
"\" has not been declared", location);
return null;
Expand All @@ -166,8 +164,7 @@ action code {:
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */

parser code {:
Main main;
emit emit;
Options options;

/* override error routines */
public void report_fatal_error(
Expand All @@ -177,7 +174,7 @@ parser code {:
done_parsing();
if (info instanceof Symbol) ErrorManager.getManager().emit_fatal(message+ "\nCan't recover from previous error(s), giving up.",(Symbol)info);
else ErrorManager.getManager().emit_fatal(message + "\nCan't recover from previous error(s), giving up.",cur_token);
System.exit(1);
throw new RuntimeException("jcup fatal error parsing grammar");
}

public void report_error(String message, Object info)
Expand Down Expand Up @@ -257,7 +254,7 @@ package_spec ::=
PACKAGE multipart_id:id SEMI
{:
/* save the package name */
parser.main.setOption("package", id.toString());
parser.options.setOption("package", id.toString());
:}
|
/* empty */
Expand All @@ -269,7 +266,7 @@ import_spec ::=
IMPORT import_id:id SEMI
{:
/* save this import on the imports list */
parser.emit.import_list.add(id.toString());
parser.options.import_list.add(id.toString());
:}
;

Expand All @@ -286,27 +283,27 @@ code_parts ::=

parser_spec ::=
PARSER multipart_id:name SEMI
{: parser.main.setOption("parser", name.toString()); :}
{: parser.options.setOption("parser", name.toString()); :}
| PARSER multipart_id:name LT typearglist:types GT SEMI
{: parser.main.setOption("parser", name.toString());
parser.main.setOption("typearg", types.toString()); :}
{: parser.options.setOption("parser", name.toString());
parser.options.setOption("typearg", types.toString()); :}
;


option_spec ::= OPTION option_list SEMI;
option_list ::= option_list COMMA option_ | option_;
option_ ::= robust_id:opt {: parser.main.setOption(opt); :}
option_ ::= robust_id:opt {: parser.options.setOption(opt); :}
| robust_id:opt EQUALS robust_id:val
{: parser.main.setOption(opt, val); :};
{: parser.options.setOption(opt, val); :};
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */

action_code_part ::=
ACTION CODE CODE_STRING:user_code SEMI?
{:
if (parser.emit.action_code!=null)
if (parser.options.action_code!=null)
ErrorManager.getManager().emit_warning("Redundant action code (skipping)");
else /* save the user included code string */
parser.emit.action_code = user_code;
parser.options.action_code = user_code;
:}
;

Expand All @@ -315,10 +312,10 @@ action_code_part ::=
parser_code_part ::=
PARSER CODE CODE_STRING:user_code SEMI?
{:
if (parser.emit.parser_code!=null)
if (parser.options.parser_code!=null)
ErrorManager.getManager().emit_warning("Redundant parser code (skipping)");
else /* save the user included code string */
parser.emit.parser_code = user_code;
parser.options.parser_code = user_code;
:}
;

Expand All @@ -327,10 +324,10 @@ parser_code_part ::=
init_code ::=
INIT WITH CODE_STRING:user_code SEMI?
{:
if (parser.emit.init_code!=null)
if (parser.options.init_code!=null)
ErrorManager.getManager().emit_warning("Redundant init code (skipping)");
else /* save the user code */
parser.emit.init_code = user_code;
parser.options.init_code = user_code;
:}
;

Expand All @@ -339,10 +336,10 @@ init_code ::=
scan_code ::=
SCAN WITH CODE_STRING:user_code SEMI?
{:
if (parser.emit.scan_code!=null)
if (parser.options.scan_code!=null)
ErrorManager.getManager().emit_warning("Redundant scan code (skipping)");
else /* save the user code */
parser.emit.scan_code = user_code;
parser.options.scan_code = user_code;
:}
;

Expand All @@ -351,10 +348,10 @@ scan_code ::=
after_reduce_code ::=
AFTER REDUCE CODE_STRING:user_code SEMI?
{:
if (parser.emit.after_reduce_code!=null)
if (parser.options.after_reduce_code!=null)
ErrorManager.getManager().emit_warning("Redundant after reduce code (skipping)");
else /* save the user code */
parser.emit.after_reduce_code = user_code;
parser.options.after_reduce_code = user_code;
:}
;

Expand Down Expand Up @@ -515,9 +512,8 @@ wild_symbol_id ::=
/* if that fails, symbol is undeclared */
if (symb == null)
{
if (ErrorManager.getManager().getErrorCount() == 0)
ErrorManager.getManager().emit_error("Symbol \"" + symid +
"\" has not been declared");
"\" has not been declared", symid$);
RESULT = null;
}
else
Expand Down Expand Up @@ -627,9 +623,9 @@ robust_id ::= /* all ids that aren't reserved words in Java */
| NONASSOC
| AFTER
| REDUCE
| error
| error:e
{:
ErrorManager.getManager().emit_error("Illegal use of reserved word");
ErrorManager.getManager().emit_error("Illegal use of reserved word", e$);
RESULT="ILLEGAL";
:}
;
Expand Down
4 changes: 2 additions & 2 deletions flex/Lexer.jflex
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import java.io.InputStreamReader;
%%

%class Lexer
%implements sym, com.github.jhoenicke.javacup.runtime.Scanner
%implements Sym, com.github.jhoenicke.javacup.runtime.Scanner
%function next_token
%type com.github.jhoenicke.javacup.runtime.Symbol
%eofclose
Expand Down Expand Up @@ -54,7 +54,7 @@ ident = ([:jletter:] | "_" ) ([:jletterdigit:] | [:jletter:] | "_" )*


%eofval{
return symbolFactory.newSymbol("EOF",sym.EOF);
return symbolFactory.newSymbol("EOF",Sym.EOF);
%eofval}

%state CODESEG
Expand Down
156 changes: 110 additions & 46 deletions src/com/github/jhoenicke/javacup/ErrorManager.java
Original file line number Diff line number Diff line change
@@ -1,49 +1,113 @@

package com.github.jhoenicke.javacup;

import java.util.Set;
import java.util.TreeSet;

import com.github.jhoenicke.javacup.runtime.Symbol;
public class ErrorManager{
private static ErrorManager errorManager;
private int errors = 0;
private int warnings = 0;
private int fatals = 0;
public int getFatalCount() { return fatals; }
public int getErrorCount() { return errors; }
public int getWarningCount() { return warnings; }
static {
errorManager = new ErrorManager();
}
public static ErrorManager getManager() { return errorManager; }
private ErrorManager(){
}

//TODO: migrate to java.util.logging
/**
* Error message format:
* ERRORLEVEL at (LINE/COLUMN)@SYMBOL: MESSAGE
* ERRORLEVEL : MESSAGE
**/
public void emit_fatal(String message){
System.err.println("Fatal: "+message);
fatals++;
}
public void emit_fatal(String message, Symbol sym){
System.err.println("Fatal: "+message+" @ "+sym);
fatals++;
}
public void emit_warning(String message){
System.err.println("Warning: " + message);
warnings++;
}
public void emit_warning(String message, Symbol sym){
System.err.println("Warning: " + message+" @ "+sym);
warnings++;
}
public void emit_error(String message){
System.err.println("Error: " + message);
errors++;
}
public void emit_error(String message, Symbol sym){
System.err.println("Error: "+message+" @ "+sym);
errors++;
}

public class ErrorManager {

private static ErrorManager errorManager;

static enum Severity {
Info,
Warning,
Error,
Fatal,
}

private int infos = 0;
private int warnings = 0;
private int errors = 0;
private int fatals = 0;

private Set<String> filter;

private ErrorManager() {
}

public static ErrorManager getManager() {
if (errorManager == null) errorManager = new ErrorManager();
return errorManager;
}

public static void clear () {
errorManager = null;
}

private Set<String> getFilter () {
if (filter == null) filter = new TreeSet<>();
return filter;
}

public int getFatalCount() {
return fatals;
}

public int getErrorCount() {
return errors;
}

public int getWarningCount() {
return warnings;
}

/**
* Error message format:
* ERRORLEVEL : MESSAGE @ Symbol: name#token=="value"(line/column)
* ERRORLEVEL : MESSAGE
**/

private void emit (Severity severity, String message, Symbol sym) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit-pick: no space before "(".

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I did not know this rule. I will respect it later.

if (sym != null && sym.value != null) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this is a good idea. What is the intention?

It looks like it stops printing multiple error messages for the same location.

Also since the ErrorManager is static, this would mean that on the second run the errors are no longer printed, doesn't it?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a filter on the same symbol. IOn the previous release only the first message is emitted and subsequent messages vanishes. With this filter, a second (third,...) message about the same symbol (should exists and have a value) is not printed. So only the first one is printed but other error about other symbols are printed too.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I forgot to reply about the second run. No problem, In Main I call a clear method which nullify the instance so the getter will recreate one fresh with all fields set to initial value.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a bit dangerous and sym.value may not even mean the right thing. The symbol is really the location in the source file where the error happened and it can be any error like undeclared symbol, symbols declared multiple times, or a unrecoverable syntax error. You may hide some error message here.

If you just don't want to get multiple warnings about undefined symbols, it would be better to do this in the parser and keep a set of symbols that were already warned about there. This way you can be sure that only these kind of double reports are omitted and you get for free the clearing of the set.

if (getFilter().contains(sym.value.toString())) return;
getFilter().add(sym.value.toString());
}
StringBuilder tmp = new StringBuilder();
tmp.append(severity.name());
tmp.append(": ");
tmp.append(message);
if (sym != null) {
tmp.append(" @ ");
tmp.append(sym);
}
System.err.println(tmp);
}

public void emit_info(String message) {
emit_info(message, null);
}

public void emit_info(String message, Symbol sym) {
emit(Severity.Info, message, sym);
infos++;
}

public void emit_warning(String message) {
emit_warning(message, null);
}

public void emit_warning(String message, Symbol sym) {
emit(Severity.Warning, message, sym);
warnings++;
}

public void emit_error(String message) {
emit_error(message, null);
}

public void emit_error(String message, Symbol sym) {
emit(Severity.Error, message, sym);
errors++;
}

public void emit_fatal(String message) {
emit_fatal(message, null);
}

public void emit_fatal(String message, Symbol sym) {
emit(Severity.Fatal, message, sym);
fatals++;
}

}
Loading