Skip to content

Instantly share code, notes, and snippets.

@steinwaywhw
Last active August 29, 2015 14:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save steinwaywhw/ccf69275822dfa88abcb to your computer and use it in GitHub Desktop.
Save steinwaywhw/ccf69275822dfa88abcb to your computer and use it in GitHub Desktop.
Custom Precedence Climbing
grammar FixityTest;
@header {
import java.util.*;
}
@members {
Map<String, String> fmap = new HashMap<>();
Map<String, Integer> pmap = new HashMap<>();
public int nextp (String op) {
String fix = fmap.get(op);
Integer p = pmap.get(op);
if (fix.equals("infixr")) return p;
if (fix.equals("infixl")) return p+1;
if (fix.equals("prefix")) return p;
if (fix.equals("postfix")) return p+1;
if (fix.equals("infix")) return p+1;
return 0;
}
}
/*
prefix 6 -;
infixr 6 ^;
infixl 3 + ;
infixl 5 * /;
infix 1 =;
postfix 7 !;
1! ! + -2 * 3 ^ 5 ^ 6 + - -4! = 5 = 6;
*/
program
: (expr[0] ';'| fixity ';')+
;
expr [int p]
: aexpr
(
// infixl infixr infix case
{(fmap.get(_input.LT(1).getText()).contains("infix")) && pmap.get(_input.LT(1).getText()) >= $p}?
op=OPERATOR
expr[nextp($op.text)]
// infix case, no assoc, stop trying to match more infix operator
{!fmap.get($op.text).equals("infix")}?
|
// postfix case
{(fmap.get(_input.LT(1).getText()).equals("postfix")) && pmap.get(_input.LT(1).getText()) >= $p}?
OPERATOR
)*
;
// atom expr
aexpr
: NUMBER
| '(' expr[0] ')'
| {fmap.get(_input.LT(1).getText()).equals("prefix")}? op=OPERATOR expr[nextp($op.text)]
;
fixity
: f=FIXITY p=NUMBER (op+=OPERATOR)+
{
for (Token t : $op) {
fmap.put(t.getText(), $f.text);
pmap.put(t.getText(), $p.int);
System.out.println (String.format("Putting %s as %s %d", t.getText(), $f.text, $p.int));
}
}
;
FIXITY: 'infix' | 'infixl' | 'infixr' | 'prefix' | 'postfix';
OPERATOR: [!+\-*/^=]+;
NUMBER: [1-9] [0-9]*;
WS: [ \n\t\r]+ -> skip;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment