Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

first set of changes #4

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
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
@@ -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
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
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
@@ -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"/>

@@ -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}" />
@@ -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">
48 changes: 22 additions & 26 deletions cup/parser.cup
Original file line number Diff line number Diff line change
@@ -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;
@@ -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;
@@ -166,8 +164,7 @@ action code {:
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */

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

/* override error routines */
public void report_fatal_error(
@@ -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)
@@ -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 */
@@ -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());
:}
;

@@ -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;
:}
;

@@ -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;
:}
;

@@ -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;
:}
;

@@ -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;
:}
;

@@ -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;
:}
;

@@ -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
@@ -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";
:}
;
4 changes: 2 additions & 2 deletions flex/Lexer.jflex
Original file line number Diff line number Diff line change
@@ -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
@@ -54,7 +54,7 @@ ident = ([:jletter:] | "_" ) ([:jletterdigit:] | [:jletter:] | "_" )*


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

%state CODESEG
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
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
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
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
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
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
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