0

我是 JFlex 和 CUP 的新手。我试图做一个简单的例子,但是当我运行解析器时,它总是给出同样的错误,它不会随着语句的识别而进步。我认为问题一定出在产品或规则上。我已将 Java 中始终使用的符号定义为终端,例如:

terminal LPAREN, RPAREN, RBRACE, LBRACE, LBRCKT, RBRCKT, COLON, SEMICOLON, ASSIGN, COMMA, DOT;
terminal PAGE, LABEL;

我将非终结符定义如下:

nonterminal START_PAGE;
nonterminal page_body, page_body_declarations_opt, page_body_declarations, page_body_declaration;

像这样的语法:

start with START_PAGE;
START_PAGE ::= PAGE page_body ;

page_body ::= LBRACE page_body_declarations_opt RBRACE ;
page_body_declarations_opt ::= | page_body_declarations ;
page_body_declaration ;
page_body_declarations ::= page_body_declarations page_body_declaration ;
page_body_declaration ::= label_declaration ;
label_declaration ::= LABEL LPAREN RPAREN SEMICOLON ;

输入数据或文件包含第 2 行的以下内容:


Page {
}

当我运行解析器时,我打印词法分析器的结果,然后我运行解析器得到以下结果:

Token: # 2 Page
Token: # 51 {
Token: # 52}
Token: # 0
Compiler has detected a syntax error at line 2 column 8
Error in line 2, column 8: Couldn't repair and continue parse

错误显示在 LBRACE 中。

我用于测试的版本是:

<jflex.version>1.8.2</jflex.version>
<cup.version>11b-20160615</cup.version>

总体思路是:

定义页面块并在内部定义其他元素,例如标签。

如果您能帮我执行这个示例,我将不胜感激。

对于规则或产生式的定义以及应如何减少 CUP,现有的信息非常稀缺。我研究过的所有例子都是算术表达式,但我没有发现更多有助于解决问题的例子。

这是我的词法分析器文件


// USER CODE

package core;

import java.io.Reader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java_cup.runtime.Symbol;
import java_cup.runtime.Scanner;
import java.nio.charset.StandardCharsets;
import java_cup.runtime.ComplexSymbolFactory;
import java_cup.runtime.ComplexSymbolFactory.Location;
import java_cup.runtime.ComplexSymbolFactory.ComplexSymbol;


/**
 * Lexer class.
 */

%% /*----------------------------------------------------------*/

%public
// Lexer class to generate
%class Lexer
%cupsym MSymbol
%function next_token
%implements MSymbol, Scanner
%type java_cup.runtime.Symbol

%unicode

%cupdebug

%char
%full

%line
%column

%eofval{
    
    return mSymbol(MSymbol.EOF);

%eofval}


/*--------------------------------------------------------------
    CODE COPIED INTO LEXER
  --------------------------------------------------------------*/
%{ 

    ComplexSymbolFactory symbolFactory;
    
    StringBuffer string = new StringBuffer();

    public Lexer(Reader in, ComplexSymbolFactory sf){
        this(in);
        symbolFactory = sf;
    }
    
    private Symbol mSymbol(int type) {
        return new Symbol(type, yyline, yycolumn);
    }
    
    private Symbol mSymbol(int type, Object value) {
        return new Symbol(type, yyline, yycolumn, value);
    }
    private void error(String message) {
        System.out.println("Error at line "+(yyline+1)+", column "+(yycolumn+1)+" : " + message);
    }

%}

/*--------------------------------------------------------------
    MACRO DECLARATIONS
  --------------------------------------------------------------*/
LineTerminator = \r|\n|\r\n
InputCharacter = [^\r\n]
//WhiteSpace     = {LineTerminator} | [\ ,\t,\f]
WhiteSpace     = [\ ,\t,\f,\t] | {LineTerminator}

/* comments */
Comment = {TraditionalComment} | {EndOfLineComment} | {DocumentationComment}

TraditionalComment   = "/*" [^*] ~"*/" | "/*" "*"+ "/"
// Comment can be the last line of the file, without line terminator.
EndOfLineComment     = "//" {InputCharacter}* {LineTerminator}?
DocumentationComment = "/**" {CommentContent} "*"+ "/"
CommentContent       = ( [^*] | \*+ [^/*] )*


%state STRING

%% /*----------------------------------------------------------*/

/* Keywords */

<YYINITIAL> {

/*-------------------------------------------------------------
    KEYWORDS
  -------------------------------------------------------------*/
    "Page"      { 
                    return mSymbol(MSymbol.PAGE, yytext()); 
                }
    
}   //------> End of Keywords


<YYINITIAL> {
    /* separators */
    "("             { return mSymbol(MSymbol.LPAREN, yytext()); }
    ")"             { return mSymbol(MSymbol.RPAREN, yytext()); }
    "{"             { return mSymbol(MSymbol.RBRACE, yytext()); }
    "}"             { return mSymbol(MSymbol.LBRACE, yytext()); }
    "["             { return mSymbol(MSymbol.LBRCKT, yytext()); }
    "]"             { return mSymbol(MSymbol.RBRCKT, yytext()); }
    ";"             { return mSymbol(MSymbol.SEMICOLON, yytext()); }
    ","             { return mSymbol(MSymbol.COMMA, yytext()); }
    "."             { return mSymbol(MSymbol.DOT, yytext()); }
    "="             { return mSymbol(MSymbol.ASSIGN, yytext()); }
    ":"             { return mSymbol(MSymbol.COLON, yytext()); }

    \"              { yybegin(STRING); string.setLength(0); }
    

    /* WHITESPACE */
    {WhiteSpace}    { /* ignore */ }

    /* comments */
    {Comment}       { /* ignore */ }
}

<STRING> {
    \"              {   
                        yybegin(YYINITIAL);
                        return mSymbol(MSymbol.STRING_LITERAL, string.toString()); 
                    }
    
}

/* error fallback */
[^]                 { 
                        this.error("Illegal character [ " + yytext() + " ]");
                    }

运行解析器时,词法分析器会检测标记。我不知道空间会发生什么。

Token: #2 Page
Token: #51 {
Token: #52 }
Token: #0 
Compiler has detected a syntax error at line 2 column 8
Error in line 2, column 8 : Couldn't repair and continue parse

文本无法修复并继续解析由解析器杯设置。

这是生成解析器时的结果

------- CUP v0.11b 20160615 (GIT 4ac7450) Parser Generation Summary -------
  0 errors and 54 warnings
  62 terminals, 7 non-terminals, and 8 productions declared, 
  producing 15 unique parse states.
  54 terminals declared but not used.
  0 non-terminals declared but not used.
  0 productions never reduced.
  0 conflicts detected (0 expected).
  Code written to "Parser.java", and "MSymbol.java".
---------------------------------------------------- (CUP v0.11b 20160615 (GIT 4ac7450))

运行解析器的代码

    ComplexSymbolFactory csf = new ComplexSymbolFactory();
    Lexer lexer = new Lexer(new BufferedReader(new FileReader(args[0], StandardCharsets.UTF_8)), csf);
    ScannerBuffer lxrBuff = new ScannerBuffer(lexer);
    Parser mParser = new Parser(lxrBuff, csf);
    mParser.parse();

提前致谢

4

1 回答 1

0

在更正 LBRACE 和 RBRACE 令牌后,我已经找到了问题的解决方案。由于使用集成了 CUP 的最新版本的 JFlex,它在 CUP 实现上使用了新的 ComplexSymbolFactory,并且必须使用此方法来存储令牌。

private Symbol mSymbol (String tokenName, int type, Object val) {
    Location left = new Location (yyline + 1, yycolumn + 1);
    Location right = new Location (yyline + 1, yycolumn + yylength ());

    return symbolFactory.newSymbol (tokenName, type, left, right, val);
}

谢谢

于 2022-01-10T16:17:32.293 回答