\d{5}(-\d{4})?
4\d{12}(\d{3})?
5[1-5]\d{14}
\d (_?\d)*
(
\. \d (_?\d)*
|
\#
[\da-f](_?[\da-f])* (\. [\da-f](_?[\da-f])*)?
\#
)?
(e [+-]? \d(_?\d)* )?
(c|a+c|a+bc|bc|ba+c|ba+bc)*(a+|a+b|b|ba+|ba+b)?
which simplifies to this:
((b|b?a+b?)?c)*(b|b?a+b?)?
or just use negative lookahead, which is trivial, but can is slower
in theory.
(a(?!ba)|b(?!b)|c)*
{
program : [
{"var" : "x"},
{"var" : "y"},
{
while : [
{"minus" : ["y", 5]},
[
{"var" : "y"},
{"read" : "x"},
{"read" : "y"},
{
"assign" : [
"x",
{
"times" : [
2,
{"plus" : [3, "y"]}
]
}
]
}
]
]
},
{"write" : 5}
]
}
S -> A M
M -> S?
A -> 'a' E | 'b' A A
E -> ('a' B | 'b' A)?
B -> 'b' E | 'a' B B
S
/ \
A M
/ \ |
a E S
| / \
A M
/|\ |
b A A
/| |\
a E a E
| |
By the way, you can use JavaCC to inform you of the conflict! Try:
PARSER_BEGIN(Test)
public class Test {
public static void main(String[] args) {
Test parser = new Test(System.in);
parser.S();
}
}
PARSER_END(Test)
TOKEN: {"a" | "b"}
void S(): {} {A() M()}
void M(): {} {(S())?}
void A(): {} {"a" E() | "b" A() A()}
void E(): {} {("a" B() | "b" A())?}
void B(): {} {"b" E() | "a" B() B()}
S S
/ \ / \
A M A M
/ \ | / \ |
a E S a E S
/ \ / \ | / \
a B A M A M
/| |\ | / \ |
b E a E a B S
| | /| |\
b E A M
| |\ \
a E
|
EXP -> ID ":=" EXP | TERM TERM_TAIL
TERM_TAIL -> ["+" TERM TERM_TAIL]
TERM -> FACTOR FACTOR_TAIL
FACTOR_TAIL -> ["*" FACTOR FACTOR_TAIL]
FACTOR -> "(" EXP ")" | ID
EXP -> ID (":=" EXP | FACTOR_TAIL TERM_TAIL)
| "(" EXP ")" FACTOR_TAIL TERM_TAIL
(all other rules are unchanged)
- *
| / \
* - 5
/ \ |
8 5 8
They are similar in that the dynamic semantics, the value produced by the expression at runtime, will be the same regardless of structure.
LETTER -> [\p{L}]
DIGIT -> [\p{Nd}]
KEYWORD -> 'fun' | 'if' | 'else'
ID -> [\p{L}$] [\p{L}\p{Nd}_@$]* - KEYWORD
NUMLIT -> DIGIT+ ('.' DIGIT+ ([Ee] [+-]? DIGIT+)?)?
CHAR -> [^\p{Cc}"\\] | ESCAPE
ESCAPE -> '\\' ([nt'"\\] | HEX {1,8} ';')
HEX -> [0-9a-fA-F]
STRINGLIT -> '"' CHAR* '"'
SYMBOL -> [-+*/!,;()]
SKIP -> [\x20\x09\x0A\x0D]
TOKEN -> NUMLIT | STRINGLIT | ID | KEYWORD | SYMBOL
PROGRAM -> FUNDECL+ EXP
FUNDECL -> 'fun'ID '(' PARAMS? ')' BODY
PARAMS -> ID (',' ID)*
BODY -> '{' (EXP ';')+ '}'
EXP -> EXP1 ('if' EXP1 'else' EXP)*
EXP1 -> EXP2 (ADDOP EXP2)*
EXP2 -> EXP3 (MULOP EXP3)*
EXP3 -> '-'? EXP4
EXP4 -> EXP5 '!'?
EXP5 -> NUMLIT | STRINGLIT | ID | CALL
CALL -> ID '(' (EXP (',' EXP)*)? ')'
ADDOP -> '+' | '-'
MULOP -> '*' | '/'
if
|
+--------------------+---------+--------------------+
| | |
case case throw
/ \ / \ |
/ call || \ up
/ / \ / \ \
|| write * ! there ;
/ \ / \ | / \
> ! - q here dowhile =
/ \ | | / \ / \
x 2 call 3 / false call \
/ \ / / \ \
. call ; . 6 \
/ \ / \ / \ / \ \
/ \ f x while = [] g []
/ \ / \ / \ / \ / \
String matches close call x & q 4 . 2
| / \ / \
tryharder >>> * person list
/ | / \
x 3 2 x