diff options
author | Kenneth Graunke <kenneth@whitecape.org> | 2010-11-03 12:47:06 -0700 |
---|---|---|
committer | Kenneth Graunke <kenneth@whitecape.org> | 2011-01-12 23:55:33 -0800 |
commit | daeb0c646e0d652bfa16d326028753ecf092c0c9 (patch) | |
tree | 989d8ba697d400d22b6db5d123d290046de14515 /src/glsl/s_expression.cpp | |
parent | 407184fe08ced99875c3abfac743a1d60857ccf2 (diff) |
ir_reader: Add a pattern matching system and use it everywhere.
Previously, the IR reader was riddled with code that:
1. Checked for the right number of list elements (via a linked list walk)
2. Retrieved references to each component (via ->next->next pointers)
3. Downcasted as necessary to make sure that each sub-component was the
right type (i.e. symbol, int, list).
4. Checking that the tag (i.e. "declare") was correct.
This was all very ad-hoc and a bit ugly. Error checking had to be done
at both steps 1, 3, and 4. Most code didn't even check the tag, relying
on the caller to do so. Not all callers did.
The new pattern matching module performs the whole process in a single
straightforward function call, resulting in shorter, more readable code.
Unfortunately, MSVC does not support C99-style anonymous arrays, so the
pattern must be declared outside of the match call.
Diffstat (limited to 'src/glsl/s_expression.cpp')
-rw-r--r-- | src/glsl/s_expression.cpp | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/src/glsl/s_expression.cpp b/src/glsl/s_expression.cpp index e420cd6e7e..a00bfa73ed 100644 --- a/src/glsl/s_expression.cpp +++ b/src/glsl/s_expression.cpp @@ -139,3 +139,49 @@ void s_list::print() printf(")"); } +// -------------------------------------------------- + +bool +s_pattern::match(s_expression *expr) +{ + switch (type) + { + case EXPR: *p_expr = expr; break; + case LIST: if (expr->is_list()) *p_list = (s_list *) expr; break; + case SYMBOL: if (expr->is_symbol()) *p_symbol = (s_symbol *) expr; break; + case NUMBER: if (expr->is_number()) *p_number = (s_number *) expr; break; + case INT: if (expr->is_int()) *p_int = (s_int *) expr; break; + case STRING: + s_symbol *sym = SX_AS_SYMBOL(expr); + if (sym != NULL && strcmp(sym->value(), literal) == 0) + return true; + return false; + }; + + return *p_expr == expr; +} + +bool +s_match(s_expression *top, unsigned n, s_pattern *pattern, bool partial) +{ + s_list *list = SX_AS_LIST(top); + if (list == NULL) + return false; + + unsigned i = 0; + foreach_iter(exec_list_iterator, it, list->subexpressions) { + if (i >= n) + return partial; /* More actual items than the pattern expected */ + + s_expression *expr = (s_expression *) it.get(); + if (expr == NULL || !pattern[i].match(expr)) + return false; + + i++; + } + + if (i < n) + return false; /* Less actual items than the pattern expected */ + + return true; +} |