Skip to content

Instantly share code, notes, and snippets.

@schleumer
Last active June 5, 2016 04:01
Show Gist options
  • Save schleumer/e9f405f87e9752e2983b50de616cd99c to your computer and use it in GitHub Desktop.
Save schleumer/e9f405f87e9752e2983b50de616cd99c to your computer and use it in GitHub Desktop.
Simple yecc and leex parser
Definitions.
WS = ([\000-\s]|%.*)
T_VAR = [A-Za-z\.\-]
Rules.
or : {token,{'T_OR',TokenLine,list_to_atom(TokenChars)}}.
and : {token,{'T_AND',TokenLine,list_to_atom(TokenChars)}}.
{T_VAR}+ : {token,{'T_VAR',TokenLine,TokenChars}}.
[()] : {token,{list_to_atom(TokenChars),TokenLine}}.
{WS}+ : skip_token.
Erlang code.
Nonterminals
V.
Terminals '(' ')' T_VAR T_AND T_OR.
Rootsymbol V.
V -> V T_AND V : {'$2', '$1', '$3'}.
V -> V T_OR V : {'$2', '$1', '$3'}.
V -> '(' V ')' : '$2'.
V -> T_VAR : '$1'.
def expr({:T_VAR, line, name}, props) do
# failsafe
Map.get(props, name) || false
end
def expr({op, left, right}, props) do
case op do
{:T_AND, line, _} -> expr(left, props) and expr(right, props)
{:T_OR, line, _} -> expr(left, props) or expr(right, props)
_ -> raise "CO-CO-COMBO BREAKER"
end
end
def parse(expression, props) do
{:ok, tokens, _} = :guardian_lexer.string(expression)
{:ok, tree} = :guardian_parser.parse(tokens)
expr(tree, props)
end
parse('fail or DOMINATE.WORLD or (view.users and delete.users) or root', %{
'view.users' => false,
'DOMINATE.WORLD' => false,
'delete.users' => false,
'root' => true
}) |> IO.inspect
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment