options { | optional, see documentation of JavaCC | |
name = value ; ... | ||
} | ||
PARSER_BEGIN(name) | identifies parser-class and filename | |
package path; | optional, defines package | |
import path; ... | optional, will be copied | |
public class name ... { | must define class of parser | |
... | ||
} | ||
PARSER_END(name) | ||
rule ... |
Names, constants, comments and embedded Java code follow the rules of Java.
Syntactic rules
type name ( ... ) throws ... : | defines methods and nonterminals/symbols | |
{ locals } | defines local variables | |
{ formula } | specifies nonterminal/symbol |
formula is a sequence of patterns:
re | regular expression, recognizes token | |
lval = re | and assignes token | |
name ( ... ) | recognizes nonterminal/symbol | |
lval = name ( ... ) | and assignes result | |
... | ... | alternative | |
( ... ) | grouping | |
( ... )* | n-times, where n >=0 | |
( ... )? or [ ... ] | optional | |
( ... )+ | n-times, where n >=1 | |
{ ... } | java programcode, e.g. with return | |
LOOKAHEAD( ... ) | controls lookahead, see documentation |
Lexical rules
< state , ... > | optional, defines name of state | |
TOKEN | Scanner returns token to parser | |
[ IGNORE_CASE ] | optional: with this option, the scanner is not sensitive to lower/upper case | |
: | ||
{ re | detects input | |
{ ... } | optional, scanner executes this while scanning | |
: state | optional, defines next state | |
| ... | ||
} |
You can ignore input with SKIP, you can collect input for the next TOKEN with MORE and you can combine input with the next TOKEN with SPECIAL_TOKEN, see documentation.
re is a regular expression:
"..." | Java string, represents itself: | |
< name : pattern > | defines pattern | |
< #name : pattern > | defines local pattern | |
< name > | references pattern | |
< EOF > | represents End Of File (EOF) |
pattern is one of the following patterns:
"..." | Java string, represents itself | |
< name > | references pattern | |
... | ... | alternative | |
( ... ) | grouping | |
( ... )* | n-times, where n >= 0 | |
( ... )? | optional | |
( ... )+ | n-times, where n >= 1 | |
[ ... , ... ] | list of characters | |
~ [ ... , ... ] | complement of a list of characters | |
"x" | one character of a list | |
"x" - "y" | an area of characters in the list |
jjtree pushes nodes for nonterminals/symbols on an internal stack and combines them typically pro nonterminal/symbol:
type name ( ... ) throws ... : | creates ASTname-node. | |
type name ( ... ) throws ... #class : | creates ASTclass-node. | |
type name ( ... ) throws ... #void : | creates no node, the same (local) effect as (the global option) NODE_DEFAULT_VOID = true. |
The scope of a nonterminal/symbol starts, whenever the nonterminal/symbol is called. Detected nonterminals/symbols store the created nodes in their scope. Postfix-operatars inline and at groups can influence, how many nodes are combined and stored:
#class(number) | creates ASTclass-nodes with number children. | |
#class(condition) | if condition is true, the ASTclass-node with all the nodes in its scope will be created. | |
#class(>1) | Special case: creates ASTclass-node, whenever more than 1 child exists. | |
#class | Special case: creates ASTclass-node with all the children in its scope. |
You can acces the nodes by using the variable jjtThis, which represents the node, which is currently created.
You can use methods like jjtGetChild(...), which returns a child node of jjtThis, and nodeCreated(), which returns if nodes were created (useful e.g. in the case that the node is conditionally created).