ANTLRWorks v1.4.3调试器随机行为(无法连接调试器)

时间:2014-04-24 11:28:54

标签: debugging antlr

如果我调试这个语法:

grammar CDBFile;

options {
    language=Java;
    TokenLabelType=CommonToken;
    output=AST;
    k=1;
    ASTLabelType=CommonTree;
}

tokens {
    IMAG_COMPILE_UNIT;
    MODULE;
}

//@lexer::namespace{Parser}
//@parser::namespace{Parser}

@lexer::header {
}

@lexer::members {
}

@parser::header {
}

@parser::members {
}


/*
 * Lexer Rules
 */

fragment LETTER :
    'a'..'z'
  | 'A'..'Z';

MODULE_NAME
    :
    (LETTER)*   
    ;

COLON   
    :   
    ':'
    ;


/*
 * Parser Rules
 */

public
compileUnit
        :   
          (basic_record)* EOF 
        ;

basic_record 
    :
    (

      'M' COLON   module_record
    | 'F' COLON function_record

    ) ('\n')?
    ;

module_record
    :   
    MODULE_NAME 
    ;

function_record
    :
    function_scope MODULE_NAME '$'
    ;

function_scope
    :
    ('G$' | 'F$' | 'L$')    
    ;

只有这个输入:

M:divide

调试器根本不会开始说

  • " 无法启动debuggerTab。超时等待连接到远程解析器"。

在此使用语法:

grammar Calculator;

options {
//DO NOT CHANGE THESE!
backtrack    = false;
k            = 1;
output       = AST;
ASTLabelType = CommonTree;
//SERIOUSLY, DO NOT CHANGE THESE!
}

tokens {
  // Imaginary tokens

  // Root
  PROGRAM;

  // function top level
  FUNCTION_DECLARATION;
  FUNCTION_HEAD;
  FUNCTION_BODY;

  DECL;
  FUN;
  // if-else-statement
  IF_STATEMENT;
  IF_CONDITION;
  IF_BODY;
  ELSE_BODY;

  // for-loop
  FOR_STATEMENT;
  FOR_INITIALIZE;
  FOR_CONDITION;
  FOR_INCREMENT;
  FOR_BODY;

  // Non-imaginary tokens
}

@lexer::header {
package at.tugraz.ist.cc;
}

@lexer::members {
}

@parser::header {
package at.tugraz.ist.cc;
}

@parser::members {
}



  //Lexer rules
ASSIGNOP :
  '=';

OR :
  '||';

AND :
  '&&';

RELOP :
  '<'
  | '<='
  | '>'
  | '>='
  | '=='
  | '!=';

SIGN :
  '+'
  | '-';

MULOP :
  '*'
  | '/'
  | '%';

NOT :
  '!';

fragment OPERATORS :
  '<'
  | '>'
  | '='
  | '+'
  | '-'
  | '/'
  | '%'
  | '*'
  | '|'
  | '&';

INT :
  '0'
  | DIGIT DIGIT0*;

fragment DIGIT :
  '1'..'9';

fragment DIGIT0 :
  '0'..'9';

BOOLEAN :
  'true'
  | 'false';

ID :
  LETTER
  (
    LETTER
    | DIGIT0
    | '_'
  )*;

fragment LETTER :
  'a'..'z'
  | 'A'..'Z';

PUNCT :
  '.'
  | ','
  | ';'
  | ':'
  | '!';

WS :
  (
    ' '
    | '\t'
    | '\r'
    | '\n'
  )

  {
   $channel = HIDDEN;
  };

LITERAL :
  '"'
  (
    LETTER
    | DIGIT
    | '_'
    | '\\'
    | OPERATORS
    | PUNCT
    | WS
  )*
  '"';





// parse rules

program :
  functions -> ^(PROGRAM functions)
  ;

functions :  
  (function_declaration functions)?
  ;

function_declaration :
  head=function_head  '{' declarations optional_stmt return_stmt rc='}' -> ^(FUNCTION_DECLARATION[$head.start, $head.text] function_head ^( FUNCTION_BODY[rc,"FUNCTION_BODY"] declarations optional_stmt? return_stmt))
  ;

function_head :
  typeInfo=type ID arguments -> ^(FUNCTION_HEAD[$typeInfo.start, "FUNCTION_HEAD"] type ID arguments?) 
  ; 

type : 

    'int'
    | 'boolean'
    | 'String'
  ;

arguments : 
  '(' ! argument_optional ')' !;

argument_optional : 
  parameter_list ? -> ^(DECL parameter_list)?  ;

parameter_list : 
  type  ID parameter_list2 -> ^(type ID) parameter_list2
  ;

parameter_list2 : 
  (','  type  ID)*  -> ^(type ID)*; 


declarations :
  (   type idlist ';' )*  ->  ^(DECL ( ^(type  idlist))*) ;

idlist : 
  ( ID idlist2 );

idlist2 : 
  ( ',' ! idlist ) ?;

optional_stmt :
  ( stmt_list ) ?;

stmt_list : 
  statement statement2;

statement2 : 
  stmt_list ?;

return_stmt : 
   'return' ^  expression ';' ! ;

statement :
  (
    compound_stmt
    | ifThenElse
    | forLoop
    | assignment ';' !
  ) ;

ifThenElse :
  (
  'if' '('  ifCondition=expression ')' ifBody=statement 'else' elseBody=statement -> ^(IF_STATEMENT ^(IF_CONDITION $ifCondition) ^(IF_BODY $ifBody) ^(ELSE_BODY $elseBody)) 
  )
;

forLoop :
  (
    'for' '(' forInitialization=assignment ';' forCondition=expression ';' forIncrement=assignment ')' forBody=statement -> 
    ^(FOR_STATEMENT ^(FOR_INITIALIZE $forInitialization) ^(FOR_CONDITION $forCondition) ^(FOR_INCREMENT $forIncrement) ^(FOR_BODY $forBody))
  )
;

compound_stmt :
  '{'! optional_stmt '}' !;

assignment :
  ID ASSIGNOP ^ expression;

expression: andExpression (OR ^ andExpression)*;
andExpression: relOPExpression (AND ^ relOPExpression)*;
relOPExpression: signExpression (RELOP ^ signExpression)*;
signExpression : mulExpression (SIGN  ^ mulExpression)*;
mulExpression : factor (MULOP ^ factor)*;

factor :
  (
    factorID
    | INT
    | BOOLEAN
    | LITERAL
    | NOT ^ factor
    | SIGN ^ factor
    | '('! expression ')' !
  );

factorID:    ID 
    ( function_call ->  ^(FUN ID function_call)  
        |   ->  ID
    )
    ;

function_call :
  '('! function_call_opt ')' !;

function_call_opt :
  extend_assign_expr_list  ? ;

extend_assign_expr_list :
  (
    expression
     extend_assign_expr_list1
  ) ;

extend_assign_expr_list1 :
  ( ',' ! extend_assign_expr_list ) ? ; 

解析像

这样的输入
int main()
{ 
  return 0;
}

工作得很好!

互联网对此问题提出了很多建议,但似乎都没有。问题是调试器是否正常工作。假设输入不是问题,语法必须是它。但是如果语法有问题,为什么解释器会为两个例子工作?

有什么想法吗?

编辑:

我注意到__Test__.java中出于某种原因只包含:

M:divide
F:G0

我在解释M:asd

时也会得到此输出
[13:47:52] Interpreting...
[13:47:52] problem matching token at 1:3 NoViableAltException('a'@[1:1: Tokens : ( T__8 | T__9 | T__10 | T__11 | T__12 | T__13 | T__14 | COLON );])
[13:47:52] problem matching token at 1:4 NoViableAltException('s'@[1:1: Tokens : ( T__8 | T__9 | T__10 | T__11 | T__12 | T__13 | T__14 | COLON );])
[13:47:52] problem matching token at 1:5 NoViableAltException('d'@[1:1: Tokens : ( T__8 | T__9 | T__10 | T__11 | T__12 | T__13 | T__14 | COLON );])

(甚至认为树是正确的)

1 个答案:

答案 0 :(得分:1)

AFAIK,调试器仅适用于Java目标。由于您的第一个语法中包含C#特定代码:

@lexer::namespace{Parser}
@parser::namespace{Parser}

没有生成.java个类(或者至少没有会编译的类),调试器会挂起(并超时)。

修改

我发现您在解析器规则中使用fragment规则:您无法做到。片段规则永远不会成为一个令牌,它们仅适用于其他词法规则。

我已经在ANTLRWorks 1.4.3中测试了没有C#代码的语法,并且没有任何问题。

您可以尝试以下方法:

  • 重启ANTLRWorks
  • 更改调试器侦听的端口(可能该端口由另一个服务或ANTLRWorks的另一个调试运行使用)
  • 使用最新版本的ANTLRWorks