元素可以包含由 ANTLR 生成的解析器解析的属性吗?如果是这样,如何? [英] can an element contain attribute as parsed by parser generated by ANTLR? if so, how?

查看:16
本文介绍了元素可以包含由 ANTLR 生成的解析器解析的属性吗?如果是这样,如何?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在关注

这是 todo.g4 的代码,见

之前的尝试:这是我的费用.g4

语法费用;付款:(付款 NL)*;付款:PAY 收款人金额=NUMBER ;接收者:姓氏=ID(姓氏=ID)?;支付:'支付';数字:[0-9]+ (',' [0-9]+)+ ('.' [0-9]+)?;ID: [a-zA-Z0-9_]+ ;NL: '\n' |'\r\n' ;WS: [\t ]+ ->跳过 ;

之前的尝试:rel="nofollow noreferrcom/simkimsia/learn-antlr-web-js/commit/728813ac275a3f2ad16d7f51ce15fcc27d40045b#commitcomment-25127606

早期尝试:rel="nofollow noreferrcom/simkimsia/learn-antlr-web-js/commit/0c32aec6ffb4b4275db86d54e9788058a2ce8759#commitcomment-25125695

解决方案

10 月 24 日 2017 年 10 月 24 日 UTC+1 的情况.

你的语法完美无缺.我用 Java 做了一个完整的测试.

文件 Expense.g4 :

语法费用;付款@init {System.out.println("费用上次更新 1853");}:(付款荷兰)*;支付: 支付接收者金额=NUMBER{System.out.println("付款找到" + $amount.text + " to " + $receiver.text);};接收者: 姓=ID(姓=ID)?;支付:'支付';数字:([0-9]+(','[0-9]+)*)('.'[0-9]*)?;ID : [a-zA-Z0-9_]+ ;NL : '\n' |'\r\n' ;WS : [\t ]+ ->频道(隐藏);//保留空格(没有空格 ==> paydeltaco98)

文件 ExpenseMyListener.java :

public class ExpenseMyListener extends ExpenseBaseListener {ExpenseParser 解析器;public ExpenseMyListener(ExpenseParser parser) { this.parser = parser;}public void exitPayments(ExpenseParser.PaymentsContext ctx) {System.out.println(">>> in ExpenseMyListener for paymentss");System.out.println(">>> 付款列表中有" + ctx.payment().size() + " 元素");for (int i = 0; i < ctx.payment().size(); i++) {System.out.println(ctx.payment(i).getText());}}public void exitPayment(ExpenseParser.PaymentContext ctx) {System.out.println(">>> 在 ExpenseMyListener 中进行支付");System.out.println(parser.getTokenStream().getText(ctx));}}

文件 test_expense.java :

import org.antlr.v4.runtime.ANTLRFileStream;导入 org.antlr.v4.runtime.ANTLRInputStream;导入 org.antlr.v4.runtime.CommonTokenStream;导入 org.antlr.v4.runtime.ParserRuleContext;导入 org.antlr.v4.runtime.tree.*;导入 java.io.FileInputStream;导入 java.io.InputStream;导入 java.io.IOException;公共类 test_expense {public static void main(String[] args) 抛出 IOException {ANTLRInputStream input = new ANTLRFileStream(args[0]);ExpenseLexer 词法分析器 = new ExpenseLexer(input);CommonTokenStream 令牌 = new CommonTokenStream(lexer);ExpenseParser parser = new ExpenseParser(tokens);ParseTree 树 = parser.payments();System.out.println("---解析结束");ParseTreeWalker walker = new ParseTreeWalker();ExpenseMyListener my_listener = new ExpenseMyListener(parser);System.out.println(">>>>即将走路");walker.walk(my_listener, tree);}}

输入文件 top.text :

支付 Acme Corp 123,456支付香蕉公司 456789.00支付查理私人 123,456.89支付德尔塔公司 98

执行:

$ export CLASSPATH=".:/usr/local/lib/antlr-4.6-complete.jar"$别名别名 a4='java -jar/usr/local/lib/antlr-4.6-complete.jar'别名 grun='java org.antlr.v4.gui.TestRig'$ a4费用.g4$ javac Ex*.java$ javac test_expense.java$ grun 费用支付 -tokens -diagnostics top.text[@0,0:2='pay',<'pay'>,1:0][@1,3:3='',,channel=1,1:3][@2,4:7='Acme',,1:4][@3,8:8='',,channel=1,1:8][@4,9:12='Corp',,1:9]...[@32,90:89='',,5:0]费用最后更新 1853向 Acme Corp 支付了 123,456 笔款项付款发现 456789.00 给 Banana Inc付款找到 123,456.89 给 charlie pte付款找到 98 给 delta co$ java test_expense top.text费用最后更新 1853向 Acme Corp 支付了 123,456 笔款项付款发现 456789.00 给 Banana Inc付款找到 123,456.89 给 charlie pte付款找到 98 给 delta co---解析结束>>>>即将走路>>>在 ExpenseMyListener 中进行支付支付 Acme Corp 123,456>>>在 ExpenseMyListener 中进行支付支付香蕉公司 456789.00>>>在 ExpenseMyListener 中进行支付支付查理私人 123,456.89>>>在 ExpenseMyListener 中进行支付支付德尔塔公司 98>>>在 ExpenseMyListener 中进行支付>>>付款列表中有 4 个元素payAcmeCorp123,456payBananaInc456789.00paycharliepte123,456.89paydeltaco98

I am following this tutorial and successfully replicated its behavior except that I am using Antlr 4.7 instead of the 4.5 that the tutorial was using.

I am trying to build a DSL for expense tracker.

Was wondering if each element can have attributes?

E.g. this is what it looks like now

This is the code for the todo.g4 as seen in https://github.com/simkimsia/learn-antlr-web-js/blob/master/todo.g4

grammar todo;

elements
    : (element|emptyLine)* EOF
    ;

element
    : '*' ( ' ' | '\t' )* CONTENT NL+
    ;

emptyLine
    : NL
    ;

NL
    : '\r' | '\n' 
    ;

CONTENT
    : [a-zA-Z0-9_][a-zA-Z0-9_ \t]*
    ;    

Meaning to say the element will also have 2 attributes such as amount and payee. To keep it simple, I will have the same sentence structure so to allow parsing to be done more easily.

the format will be pay [payee] [amount]

the example is pay Acme Corp 123,789.45

so the payee is Acme Corp and the amount is 12378945 as expressed in integers to denote the amount in denominations of cents

another example is pay Banana Inc 700

so the payee is Banana Inc and the amount is 70000 as expressed in integers to denote the amount in denominations of cents

I am guessing I need to change the todo.g4 and then re generate the parser.

Can an element have other attributes? If so, how do I get started?

UPDATE

This is my latest attempts ranked with latest updates on top:

I just figured out how to use grun and testRig. Thanks @Raven for that tip.

latest attempt: My latest expense.g4 (only difference from earlier attempt is the regex for payment)

grammar expense;

payments: (payment NL)* ;  
payment: PAY receiver amount=NUMBER ;  
receiver: surname=ID (lastname=ID)? ;  

PAY: 'pay' ;
NUMBER: ([0-9]+(','[0-9]+)*)('.'[0-9]*)?;
ID: [a-zA-Z0-9_]+ ;
NL: '\n' | '\r\n' ;  
WS: [\t ]+ -> skip ;

Earlier attempt: This is my expense.g4

grammar expense;

payments: (payment NL)* ;  
payment: PAY receiver amount=NUMBER ;  
receiver: surname=ID (lastname=ID)? ;  

PAY: 'pay' ;
NUMBER: [0-9]+ (',' [0-9]+)+ ('.' [0-9]+)? ;  
ID: [a-zA-Z0-9_]+ ;
NL: '\n' | '\r\n' ;  
WS: [\t ]+ -> skip ;

Earlier attempt: https://github.com/simkimsia/learn-antlr-web-js/commit/728813ac275a3f2ad16d7f51ce15fcc27d40045b#commitcomment-25127606

Earlier attempt: https://github.com/simkimsia/learn-antlr-web-js/commit/0c32aec6ffb4b4275db86d54e9788058a2ce8759#commitcomment-25125695

解决方案

Situation on October 24. 2017 at 19:00 UTC+1.

Your grammar works perfectly. I made a full test in Java.

File Expense.g4 :

grammar Expense;

payments
@init {System.out.println("Expense last update 1853");}
    : (payment NL)*
    ;

payment
    : PAY receiver amount=NUMBER
      {System.out.println("Payement found " + $amount.text + " to " + $receiver.text);}
    ;

receiver
    : surname=ID (lastname=ID)?
    ; 

PAY    : 'pay' ;
NUMBER : ([0-9]+(','[0-9]+)*)('.'[0-9]*)? ;
ID     : [a-zA-Z0-9_]+ ;
NL     : '\n' | '\r\n' ;  
WS     : [\t ]+ -> channel(HIDDEN) ; // keep the spaces (witout spaces ==> paydeltaco98)

File ExpenseMyListener.java :

public class ExpenseMyListener extends ExpenseBaseListener {
    ExpenseParser parser;
    public ExpenseMyListener(ExpenseParser parser) { this.parser = parser; }

    public void exitPayments(ExpenseParser.PaymentsContext ctx) {
        System.out.println(">>> in ExpenseMyListener for paymentsss");
        System.out.println(">>> there are " + ctx.payment().size() + " elements in the list of payments");
        for (int i = 0; i < ctx.payment().size(); i++) {
            System.out.println(ctx.payment(i).getText());
        }
    }

    public void exitPayment(ExpenseParser.PaymentContext ctx) {
        System.out.println(">>> in ExpenseMyListener for payment");
        System.out.println(parser.getTokenStream().getText(ctx));
    }
}

File test_expense.java :

import org.antlr.v4.runtime.ANTLRFileStream;
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.*;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;

public class test_expense {
    public static void main(String[] args) throws IOException {
        ANTLRInputStream input = new ANTLRFileStream(args[0]);
        ExpenseLexer lexer = new ExpenseLexer(input);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        ExpenseParser parser = new ExpenseParser(tokens);
        ParseTree tree = parser.payments();
        System.out.println("---parsing ended");
        ParseTreeWalker walker = new ParseTreeWalker();
        ExpenseMyListener my_listener = new ExpenseMyListener(parser);
        System.out.println(">>>> about to walk");
        walker.walk(my_listener, tree);
    }
}

Input file top.text :

pay Acme Corp 123,456
pay Banana Inc 456789.00
pay charlie pte 123,456.89
pay delta co 98

Execution :

$ export CLASSPATH=".:/usr/local/lib/antlr-4.6-complete.jar"
$ alias
alias a4='java -jar /usr/local/lib/antlr-4.6-complete.jar'
alias grun='java org.antlr.v4.gui.TestRig'
$ a4 Expense.g4 
$ javac Ex*.java
$ javac test_expense.java 
$ grun Expense payments -tokens -diagnostics top.text
[@0,0:2='pay',<'pay'>,1:0]
[@1,3:3=' ',<WS>,channel=1,1:3]
[@2,4:7='Acme',<ID>,1:4]
[@3,8:8=' ',<WS>,channel=1,1:8]
[@4,9:12='Corp',<ID>,1:9]
...
[@32,90:89='<EOF>',<EOF>,5:0]
Expense last update 1853
Payement found 123,456 to Acme Corp
Payement found 456789.00 to Banana Inc
Payement found 123,456.89 to charlie pte
Payement found 98 to delta co

$ java test_expense top.text 
Expense last update 1853
Payement found 123,456 to Acme Corp
Payement found 456789.00 to Banana Inc
Payement found 123,456.89 to charlie pte
Payement found 98 to delta co
---parsing ended
>>>> about to walk
>>> in ExpenseMyListener for payment
pay Acme Corp 123,456
>>> in ExpenseMyListener for payment
pay Banana Inc 456789.00
>>> in ExpenseMyListener for payment
pay charlie pte 123,456.89
>>> in ExpenseMyListener for payment
pay delta co 98
>>> in ExpenseMyListener for paymentsss
>>> there are 4 elements in the list of payments
payAcmeCorp123,456
payBananaInc456789.00
paycharliepte123,456.89
paydeltaco98

这篇关于元素可以包含由 ANTLR 生成的解析器解析的属性吗?如果是这样,如何?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆