How to handle error in parser javacc - javacc

in attachment, my parser generated with javacc in eclipse. I don't know as to handle errors of sintax in my parser.
how I can to do? what ways there are?
I prefer if you can posting your code that show it.
Thank you very much in advanced.
/**
* JavaCC template file created by SF JavaCC plugin 1.5.17+ wizard for JavaCC 1.5.0+
*/
options
{
JDK_VERSION = "1.5";
IGNORE_CASE = true;
LOOKAHEAD = 2;
static = true;
}
PARSER_BEGIN(MyParser)
import java.io.* ;
public class MyParser
{
public static void main(String args []) throws ParseException
{
Token t;
MyParserTokenManager tm;
int numToken = 0;
if (args.length<1) {
System.out.println("Sorgente non specificato");
System.exit(1);
}
try {
java.io.InputStream infile;
infile = new java.io.FileInputStream(args[0]);
tm = new MyParserTokenManager(new SimpleCharStream(infile));
}
catch (java.io.FileNotFoundException e) {
System.out.println("File "+args[0]+" non trovato");
return;
} // catch
t = tm.getNextToken();
numToken++;
while(t.kind != MyParserConstants.EOF){
t = tm.getNextToken();
System.out.printf("%s\t %s\n",tokenImage[t.kind],t.image);
numToken++;
}// while
}
static void error_skipto(int kind) {
ParseException e = generateParseException(); // generate the exception object.
System.out.println(e.toString()); // print the error message
Token t;
do {
t = getNextToken();
} while (t.kind != kind);
}
}
PARSER_END(MyParser)
void Stm() :
{}
{
try {
(
SE()
|
MENTRE()
|
DO()
|
PER()
|
condizione()
|
espressione()
|
expres()
)
}catch (ParseException e) {
error_skipto(PV);
}
}
SKIP :
{
" "
| "\r"
| "\t"
| "\n"
}
TOKEN : /* OPERATORS */
{
<PIU: "+">
| <MENO: "-">
| <PER: "*">
| <DIV: "/">
}
TOKEN :
{
<PAR_SIN: "(">
| <PAR_DES: ")">
| <QUAD_SIN: "[">
| <QUAD_DES: "]">
| <UGUALE: "==">
| <VIRGOLA: ",">
| <ASS: "=">
| <NEG: "?=">
| <PV: ";">
| <FOR: "da">
| <TO: "a">
| <IF: "se">
| <ELSE: "altrimenti">
| <END_IF: "fine">
| <WHILE: "mentre">
| <DO: "esegui">
| <COST_INT: (["0"-"9"])+>
| <ID: ["a"-"z","A"-"Z"]>
}
void SE() :
{}
{
(<IF> <QUAD_SIN> condizione() <QUAD_DES> <PAR_SIN> espressione() <PV> <PAR_DES> <END_IF>)
| (<IF> <QUAD_SIN> condizione() <QUAD_DES> <PAR_SIN> espressione() <PV> <PAR_DES> <ELSE> <PAR_SIN>
espressione() <PV> <PAR_DES> <END_IF>)
}
void MENTRE() :
{}
{
<WHILE> <QUAD_SIN> condizione() <QUAD_DES> <PAR_SIN> espressione() <PV> <PAR_DES>
}
void DO() :
{}
{
<DO> <PAR_SIN> espressione() <PV> <PAR_DES> <WHILE> <QUAD_SIN> condizione() <QUAD_DES> <PV>
}
void PER() :
{}
{
<FOR> (<ID>)+ <ASS> <COST_INT> <TO> (<COST_INT>)+ <PAR_SIN> espressione() <PV> <PAR_DES>
}
void condizione():
{ }
{
(<ID>)+ (<NEG> | <UGUALE>) ((<ID>)+ | (<COST_INT>)+)
}
void espressione ():
{}
{
(<ID>)+ <ASS> ((<ID>)+ | (<COST_INT>)+ | expres() )
}
void expres() :
{}
{
((<ID>)+ <PIU> ((<ID>)+ | (<COST_INT>)+))
| ((<ID>)+ <MENO> ((<ID>)+ | (<COST_INT>)+))
| ((<ID>)+ <PER> ((<ID>)+ | (<COST_INT>)+))
| ((<ID>)+ <DIV> ((<ID>)+ | (<COST_INT>)+))
}

Related

Testing JavaCC on a File?

So after I compile my code, I want it to read input from a file instead of the command line.
So instead of doing this:
javacc Ex.jj
javac *.java
java Ex "x+2"
I want to do this:
javacc Ex.jj
javac *.java
java test.txt
Where test.txt has this in it:
"x+4"
You can declare a class with a main method in your syntax file:
options {
STATIC = false;
IGNORE_CASE = false;
}
PARSER_BEGIN(Ex)
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.IOException;
public class Ex {
public static void main(String[] args) {
try (InputStream in = new FileInputStream(args[0])) {
Ex parser = new Ex(in, "UTF-8");
double r = parser.expr();
System.out.println("Result: " + r);
} catch (ParseException e) {
e.printStackTrace();
}
}
}
PARSER_END(Ex)
...
SKIP : { " " | "\r" | "\n" | "\t" }
TOKEN: {
...
}
double expr(): {
}
{
...
}

How not to match a token within quote like “hello w"orld in javacc

I'm doing a redis-cli parser by using javacc. I have to handle the quote
for example set "a b" "cd", I hope key token is a b and value token is cd.
There is my solution:
RedisCommand.java
package com.demo.command;
public interface RedisCommand {
}
SetCommand .java
package com.demo.command;
public class SetCommand implements RedisCommand{
private String key;
private String value;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
RedisCommand.jj
options {
STATIC = false;
DEBUG_PARSER=true;
}
PARSER_BEGIN(RedisCommandParser)
package com.demo.parser;
import com.demo.command.*;
import java.util.*;
public class RedisCommandParser {
public static void main(String args[]) throws ParseException {
RedisCommandParser parser = new RedisCommandParser(System.in);
parser.RedisCommand();
}
}
PARSER_END(RedisCommandParser)
SKIP :
{
<WHITESPACE: " " | "\t" | "\n" | "\r">
}
TOKEN :
{
<K_SET: "set">
}
TOKEN :
{
<SINGLE_QUOTE: "'">
| <DOUBLE_QUOTE: "\"">
| <SINGLE_STRING: <SINGLE_QUOTE> ((~["'"]) | "\\'" )+ <SINGLE_QUOTE>>
| <DOUBLE_STRING: <DOUBLE_QUOTE> ((~["\""]) | "\\\"" )+ <DOUBLE_QUOTE>>
| <RAW_STRING: (~[" "])+>
}
RedisCommand RedisCommand() :
{
RedisCommand command = null;
}
{
command=SetCommand() <EOF>
{
return command;
}
}
SetCommand SetCommand() :
{
SetCommand command = new SetCommand();
String key = null;
String value = null;
}
{
<K_SET> key=StringParam() value=StringParam()
{
command.setKey(key);
command.setValue(value);
return command;
}
}
String StringParam() :
{
String s = null;
Token token = null;
String im = null;
}
{
(token=<SINGLE_STRING> { im=token.image; s=im.substring(1, im.length()-1);}
| token=<DOUBLE_STRING> { im=token.image; s=im.substring(1, im.length()-1);}
| s=RawString()
)
{return s;}
}
String RawString() :
{}
{
/* for reserved word
* support like 'set set set'
*/
(<K_SET>
| <RAW_STRING>
)
{
return token.image;
}
}
SetCommandTest.java
package com.demo.command;
import com.demo.parser.ParseException;
import com.demo.parser.RedisCommandParser;
import org.junit.Test;
import java.io.StringReader;
public class SetCommandTest {
#Test
public void test() throws ParseException {
//test1
_test("set a b", "a", "b");
//test2
_test("set \"a b\" cd", "a b", "cd");
//test3
_test("set a\"b c\"d", "a\"b", "c\"d");
//test4
_test("set \"ab c\"d", "\"ab", "c\"d");
}
private void _test(String line, String expectKey, String expectValue) throws ParseException {
RedisCommandParser parser = new RedisCommandParser(new StringReader(line));
SetCommand command = (SetCommand) parser.RedisCommand();
String key = command.getKey();
assert key.equals(expectKey) : String.format("command[%s] key[%s] expect[%s]", line, key, expectKey);
String value = command.getValue();
assert value.equals(expectValue) : String.format("command[%s] value[%s] expect[%s]", line, value, expectValue);
}
}
test4 in SetCommandTest failed, error message is
Call: RedisCommand
Call: SetCommand
Consumed token: <"set" at line 1 column 1>
Call: StringParam
Consumed token: <<DOUBLE_STRING>: ""ab c"" at line 1 column 5>
Return: StringParam
Call: StringParam
Call: RawString
Consumed token: <<RAW_STRING>: "d" at line 1 column 11>
Return: RawString
Return: StringParam
Return: SetCommand
Consumed token: <<EOF> at line 1 column 11>
Return: RedisCommand
java.lang.AssertionError: command[set "ab c"d] key[ab c] expect["ab]
at com.demo.command.SetCommandTest._test(SetCommandTest.java:33)
at com.demo.command.SetCommandTest.test(SetCommandTest.java:26)
It take "ab c" as <DOUBLE_STRING>, which is not what I want. I think the problem is <DOUBLE_STRING>, quote after space and quote before space should work fine. Not all quote string is <DOUBLE_STRING>. but I don't know how to do. Please help me

Reusable search function javafx

I have a program that searches an observable list and displays all of the matching cases on the table. The search works fine, but I am only able to run this part of the program once. The search button stops responding after the program has returned to displaying the full observable list.
I have a separate class(Search.class) that handles all of the logic for searching the observable list.
The code for the search button and text field are below:
partSearchBtn.setOnAction(searchPartEvent ->{
ObservableList<Part> searchPartDisplay = FXCollections.observableArrayList();
String searchQuery = partSearchField.getText();
try{
searchPartDisplay = Search.searchPartByNumber(Integer.parseInt(searchQuery));
partTable.setItems(searchPartDisplay);
partSearchBtn.setText("Clear");
partSearchBtn.setOnAction(clearSearchEvent ->{
partSearchBtn.setText("Search");
partTable.setItems(Inventory.partBin);
});
} catch(NumberFormatException hasText){
searchPartDisplay = Search.searchPartByText(searchQuery);
partTable.setItems(searchPartDisplay);
partSearchBtn.setText("Clear");
partSearchBtn.setOnAction(clearSearchEvent ->{
partSearchBtn.setText("Search");
partTable.setItems(Inventory.partBin);
});
}
});
What changes would I need to make to re-run the search process?
Or should I turn this into a method as part of my Search class that I can reuse?
The search logic is below:
package inventorymngmnt;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
public class Search {
public static ObservableList<Part> searchPartByNumber(int inNum){
ObservableList<Part> searchBin = FXCollections.observableArrayList();
for(Part e: Inventory.partBin){
boolean typeCaseIn = (e.getClass() == Inhouse.class);
if(typeCaseIn == true){
Inhouse testIn = (Inhouse) e;
if(inNum == testIn.getMachineID())
searchBin.add(e);
}
if((inNum == e.getPartID()) || (inNum == e.getInstock()) || (inNum == e.getMax())
|| (inNum == e.getMin()) || ((double)inNum == e.getPrice())
|| (Integer.toString(inNum).contains(e.getName()))){
searchBin.add(e);
}
}
return searchBin;
}
public static ObservableList<Part> searchPartByText(String inString){
ObservableList<Part> searchBin = FXCollections.observableArrayList();
for(Part e: Inventory.partBin){
boolean typeCaseOut = (e.getClass() == Outsourced.class);
if(typeCaseOut == true){
Outsourced testOut = (Outsourced) e;
if(inString.equals(testOut.getCompanyName())){
searchBin.add(e);
}
}
if(inString.equals(e.getName())){
searchBin.add(e);
}
}
return searchBin;
}
public static ObservableList<Part> searchProdByNumber(int inNum){
ObservableList<Part> searchProd = FXCollections.observableArrayList();
for(Part e: Inventory.partBin){
boolean typeCaseIn = (e.getClass() == Inhouse.class);
if(typeCaseIn == true){
Inhouse testIn = (Inhouse) e;
if(inNum == testIn.getMachineID())
searchProd.add(e);
}
if((inNum == e.getPartID()) || (inNum == e.getInstock()) || (inNum == e.getMax())
|| (inNum == e.getMin()) || ((double)inNum == e.getPrice())
|| (Integer.toString(inNum).equals(e.getName()))){
searchProd.add(e);
}
}
return searchProd;
}
public static ObservableList<Part> searchProdByText(String inString){
ObservableList<Part> searchProd = FXCollections.observableArrayList();
for(Part e: Inventory.partBin){
boolean typeCaseOut = (e.getClass() == Outsourced.class);
if(typeCaseOut == true){
Outsourced testOut = (Outsourced) e;
if(inString.equals(testOut.getCompanyName())){
searchProd.add(e);
}
}
if(inString.equals(e.getName())){
searchProd.add(e);
}
}
return searchProd;
}
}
It doesn't work, because when you clear the search, the action on the button is still set to clear the search...
Consider a different strategy entirely. You can use a FilteredList as the list for the table. Then just toggle the predicate on the list:
Predicate<Part> noFilter = part -> true;
FilteredList<Part> filteredParts = new FilteredList<>(Inventory.partBin, noFilter);
partTable.setItems(filteredParts);
partSearchBtn.setOnAction(searchPartEvent -> {
if (filteredParts.getPredicate()==noFilter) {
String searchQuery = partSearchField.getText();
try {
int searchNumber = Integer.parseInt(searchQuery);
filteredParts.setPredicate(part -> Search.filterByNumber(part, searchNumber));
} catch (NumberFormatException exc) {
filteredParts.setPredicate(part -> Search.filterByText(part, searchQuery));
}
} else {
filteredParts.setPredicate(noFilter);
}
});
partSearchButton.textProperty().bind(Bindings
.when(filteredParts.predicateProperty().isEqualTo(noFilter))
.then("Search")
.otherwise("Clear"));
and
public class Search {
public static boolean filterByNumber(Part part, int number) {
if (part.getClass() == Inhouse.class) {
Inhouse testIn = (Inhouse) part ;
if (testIn.getMachineID() == number) {
return true ;
}
}
if((number == part.getPartID()) || (number == part.getInstock()) || (number == part.getMax())
|| ( number == part.getMin()) || ((double) number == part.getPrice())
|| (Integer.toString(number).contains(part.getName()))){
return true ;
}
return false ;
}
public static boolean filterByText(Part part, String text) {
//similarly...
}
}

want to use updateMessage("...") in a Class that is not an Task

I want to use updateMessage("...") in a Class that is not an Task.
How can I solve this Problem?
Is it possible to give a Task Handle which can perform a updateMessage("...") to a Function?
import javafx.concurrent.Task;
public class TestTask extends Task<Void> {
private final static int COUNT = 1000;
#Override
protected Void call() {
doTaskStuff("Found ");
return null;
}
public void doTaskStuff(String s) {
for (int i = 0; i < COUNT; i++) {
System.out.println(i);
this.updateProgress(i, COUNT);
this.updateMessage(s + (i + 1) + "!");
Dummy.dummy(this, i);
try {
Thread.sleep(1);
} catch (InterruptedException interruptedException) {
}
}
}
}
class Dummy {
public static void dummy(TestTask testTask, int i) {
String s = "";
if (i == 0) {
s = "i == 0";
} else {
s = "i != 0";
}
testTask.updateMessage(s);// does not work
}
}
The issue here is the method being protected. Of course you could override the method and increase the visibility, but this would imho be a bad approach:
#Override
public void updateMessage(String message) {
super.updateMessage(message);
}
Note that the method sets a single message, therefore you could just return the value:
updateMessage(Dummy.dummy(i));
public static String dummy(int i) {
return (i == 0) ? "i == 0" : "i != 0";
}
For multiple updates you could also provide access to this kind of functionality using an interface:
Dummy.dummy(this::updateMessage, i);
public static void dummy(Consumer<String> updater, int i) {
updater.accept((i == 0) ? "i == 0" : "i != 0");
}

How to set value to JTextField which is uneditable and and should not be considered in validation?

Hi i want to set the JTextField like this ( ) - . example (999) 999-9999 like this format and when i validate this format should not be considered and when i press backspace or delete it should not be deleted. Please help me regarding this.
To make it uneditable you should do:
(object of JTextField).setEditable(false);
and I am not clear about other two Questions, can you explain it please.
I Hope this will help you:
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
import javax.swing.JTextArea;
public class Format extends JFrame {
public JTextArea ja;
public static void main(String args[]) {
Format ft = new Format();
}
Format() {
ja = new JTextArea("Enter Phone Number:");
ja.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent ke) {
if (ke.getKeyCode() == ke.VK_ENTER) {
String st = ja.getText();
ja.setText("");
char[] ch = st.toCharArray();
if(ch.length==10){
for (int i = 0; i < ch.length; i++) {
if (i == 0) {
ja.append("(" + ch[i]);
} else if (i == 3) {
ja.append(")" + " " + ch[i]);
} else if (i == 6) {
ja.append("-" + ch[i]);
} else {
ja.append("" + ch[i]);
}
}
ja.setEditable(false);
}
}
}
});
add(ja, BorderLayout.NORTH);
setSize(new Dimension(500, 500));
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
}

Resources