[antlr-interest] c target - bug

Юрушкин Михаил yurushkin at rambler.ru
Thu Oct 22 14:51:29 PDT 2009


line 2086
ErrorType: last closing scope is redundant.
> while ( (stream_term != NULL && stream_term->hasNext(stream_term))  
> ||stream_SIGN != NULL && stream_SIGN->hasNext(stream_SIGN))  )


====================
LEXER:


lexer grammar MathLexer;

options {
     language = C;
}


APOSTROPHE: '\''; // for derivative
ASSIGN: '=';
CARET: '^'; // for exponentiation
FUNCTIONS: 'functions'; // for list command
HELP: '?' | 'help';
LEFT_PAREN: '(';
LIST: 'list';
PRINT: 'print';
RIGHT_PAREN: ')';
SIGN: '+' | '-';
VARIABLES: 'variables'; // for list command

NUMBER: INTEGER | FLOAT;
fragment FLOAT: INTEGER '.' '0'..'9'+;
fragment INTEGER: '0' | SIGN? '1'..'9' '0'..'9'*;
NAME: LETTER (LETTER | DIGIT | '_')*;
STRING_LITERAL: '"' NONCONTROL_CHAR* '"';

fragment NONCONTROL_CHAR: LETTER | DIGIT | SYMBOL | SPACE;
fragment LETTER: LOWER | UPPER;
fragment LOWER: 'a'..'z';
fragment UPPER: 'A'..'Z';
fragment DIGIT: '0'..'9';
fragment SPACE: ' ' | '\t';

// Note that SYMBOL does not include the double-quote character.
fragment SYMBOL: '!' | '#'..'/' | ':'..'@' | '['..'`' | '{'..'~';

// Windows uses \r\n. UNIX and Mac OS X use \n.
// To use newlines as a terminator,
// they can't be written to the hidden channel!
NEWLINE: ('\r'? '\n')+;
WHITESPACE: SPACE+ { $channel = HIDDEN; };


========================================

PARSER:

parser grammar MathParser;

options {
     // We're going to output an AST.
     output = AST;
     language = C;

     // We're going to use the tokens defined in our MathLexer grammar.
     tokenVocab = MathLexer;
}

// These are imaginary tokens that will serve as parent nodes
// for grouping other tokens in our AST.
tokens {
     COMBINE;
     DEFINE;
     DERIVATIVE;
     FUNCTION;
     POLYNOMIAL;
     TERM;
}

@parser::includes
{
     #include <string>
     using std::string;

     #define getTokenText(token) string((char*)token->getText(token)->chars)
}



// This is the "start rule".
// EOF is a predefined token that represents the end of input.
// The "start rule" should end with this.
// Note the use of the ! AST operator
// to avoid adding the EOF token to the AST.
script: statement* EOF!;

statement: assign | define | interactiveStatement | combine | print;

// These kinds of statements only need to be supported
// when reading input from the keyboard.
interactiveStatement: help | list;

// Examples of input that match this rule include
// "a = 19", "a = b", "a = f(2)" and "a = f(b)".
assign: NAME ASSIGN value terminator -> ^(ASSIGN NAME value);

value: NUMBER | NAME | functionEval;

// A parenthesized group in a rule alternative is called a "subrule".
// Examples of input that match this rule include "f(2)" and "f(b)".
functionEval
     : fn=NAME LEFT_PAREN (v=NUMBER | v=NAME) RIGHT_PAREN -> ^(FUNCTION $fn
$v);

// EOF cannot be used in lexer rules, so we made this a parser rule.
// EOF is needed here for interactive mode where each line entered ends in
EOF
// and for file mode where the last line ends in EOF.
terminator: NEWLINE | EOF;

// Examples of input that match this rule include
// "f(x) = 3x^2 - 4" and "g(x) = y^2 - 2y + 1".
// Note that two parameters are passed to the polynomial rule.
define
     : fn=NAME LEFT_PAREN fv=NAME RIGHT_PAREN ASSIGN
       polynomial[getTokenText($fn), getTokenText($fv)] terminator
       -> ^(DEFINE $fn $fv polynomial);

// Examples of input that match this rule include
// "3x2 - 4" and "y^2 - 2y + 1".
// fnt = function name text; fvt = function variable text
// Note that two parameters are passed in each invocation of the term rule.
polynomial[string fnt, string fvt]
     : term[$fnt, $fvt] (SIGN term[$fnt, $fvt])*
       -> ^(POLYNOMIAL term (SIGN term)*);

// Examples of input that match this rule include
// "4", "4x", "x^2" and "4x^2".
// fnt = function name text; fvt = function variable text
term[string fnt, string fvt]
     // tv = term variable
     : c=coefficient? (tv=NAME e=exponent?)?
       // What follows is a validating semantic predicate.
       // If it evaluates to false, a FailedPredicateException will be
thrown.
       // It is testing whether the term variable matches the function
variable.
       { tv == 0 ? true : getTokenText($tv) == $fvt }?
       -> ^(TERM $c? $tv? $e?)
     ;
     // This catches bad function definitions such as
     // f(x) = 2y
     catch [3] {
       throw 0;
     }

coefficient: NUMBER;

// An example of input that matches this rule is "^2".
exponent: CARET NUMBER -> NUMBER;

// Inputs that match this rule are "?" and "help".
help: HELP terminator -> HELP;

// Inputs that match this rule include
// "list functions" and "list variables".
list
     : LIST listOption terminator -> ^(LIST listOption);

// Inputs that match this rule are "functions" and "variables".
listOption: FUNCTIONS | VARIABLES;

// Examples of input that match this rule include
// "h = f + g" and "h = f - g".
combine
     : fn1=NAME ASSIGN fn2=NAME op=SIGN fn3=NAME terminator
       -> ^(COMBINE $fn1 $op $fn2 $fn3);

// An example of input that matches this rule is
// print "f(" a ") = " f(a)
print
     : PRINT printTarget* terminator -> ^(PRINT printTarget*);

// Examples of input that match this rule include
// 19, 3.14, "my text", a, f(), f(2), f(a) and f'().
printTarget
     : NUMBER -> NUMBER
     | sl=STRING_LITERAL -> $sl
     | NAME -> NAME
     // This is a function reference to print a string representation.
     | NAME LEFT_PAREN RIGHT_PAREN -> ^(FUNCTION NAME)
     | functionEval
     | derivative
     ;

// An example of input that matches this rule is "f'()".
derivative
     : NAME APOSTROPHE LEFT_PAREN RIGHT_PAREN -> ^(DERIVATIVE NAME);


              	        	}

-- 
Best regards,
Michael


More information about the antlr-interest mailing list