123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282 |
- package kawa.lang;
- import gnu.expr.*;
- import gnu.kawa.format.Printable;
- import gnu.kawa.format.ReportFormat;
- import gnu.kawa.functions.DisplayFormat;
- import gnu.kawa.io.OutPort;
- import gnu.lists.*;
- import gnu.mapping.*;
- import gnu.text.*;
- import java.io.*;
- public class SyntaxRules extends Procedure1
- implements Printable, Externalizable {
- /** The list of literal identifiers as specified in the syntax-rules form.
- */
- Object[] literal_identifiers;
- SyntaxRule[] rules;
- /* The largest (num_variables+template_identifier.length) for any rule. */
- int maxVars = 0;
- public SyntaxRules() {
- }
- /** The compiler generates calls to this constructor. */
- public SyntaxRules(Object[] literal_identifiers, SyntaxRule[] rules,
- int maxVars, Object name) {
- this.literal_identifiers = literal_identifiers;
- this.rules = rules;
- this.maxVars = maxVars;
- if (name != null)
- this.setSymbol(name);
- }
- public SyntaxRules(Object ellipsis, Object[] literal_identifiers,
- Object srules, Translator tr) {
- Macro curMacro = tr.currentMacroDefinition;
- if (curMacro != null) {
- Object curName = curMacro.getSymbol();
- if (curName != null)
- this.setSymbol(curName);
- }
- this.literal_identifiers = literal_identifiers;
- int rules_count = Translator.listLength(srules);
- if (rules_count < 0) {
- rules_count = 0;
- tr.syntaxError ("missing or invalid syntax-rules");
- }
- this.rules = new SyntaxRule [rules_count];
- Pair rules_pair;
- // SyntaxForm, if any, wrapping rest of rules list.
- SyntaxForm rules_syntax = null;
- for (int i = 0; i < rules_count; i++, srules = rules_pair.getCdr()) {
- while (srules instanceof SyntaxForm) {
- rules_syntax = (SyntaxForm) srules;
- srules = rules_syntax.getDatum();
- }
- rules_pair = (Pair) srules;
- // SyntaxForm, if any, wrapping the current rule.
- SyntaxForm rule_syntax = rules_syntax;
- Object syntax_rule = rules_pair.getCar();
- while (syntax_rule instanceof SyntaxForm) {
- rule_syntax = (SyntaxForm) syntax_rule;
- syntax_rule = rule_syntax.getDatum();
- }
- if (! (syntax_rule instanceof Pair)) {
- tr.error('e', "missing pattern in syntax rule #" + i);
- return;
- }
- // SyntaxForm, if any, wrapping the current rule's pattern.
- SyntaxForm pattern_syntax = rule_syntax;
- Pair syntax_rule_pair = (Pair) syntax_rule;
- Object pattern = syntax_rule_pair.getCar();
- String save_filename = tr.getFileName();
- int save_line = tr.getLineNumber();
- int save_column = tr.getColumnNumber();
- try {
- // SyntaxForm, if any, wrapping the current rule's template.
- SyntaxForm template_syntax = rule_syntax;
- tr.setLine(syntax_rule_pair);
- syntax_rule = syntax_rule_pair.getCdr();
- while (syntax_rule instanceof SyntaxForm) {
- template_syntax = (SyntaxForm) syntax_rule;
- syntax_rule = template_syntax.getDatum();
- }
- if (! (syntax_rule instanceof Pair)) {
- tr.error('e', "missing template in syntax rule #" + i);
- return;
- }
- syntax_rule_pair = (Pair) syntax_rule;
- if (syntax_rule_pair.getCdr() != LList.Empty) {
- Object save = tr.pushPositionOf(syntax_rule_pair.getCdr());
- tr.error('e', "junk after syntax rule #" + i);
- tr.popPositionOf(save);
- return;
- }
- Object template = syntax_rule_pair.getCar();
- PatternScope patternScope = PatternScope.push(tr);
- tr.push(patternScope);
- try {
- while (pattern instanceof SyntaxForm) {
- pattern_syntax = (SyntaxForm) pattern;
- pattern = pattern_syntax.getDatum();
- }
- StringBuilder programbuf = new StringBuilder();
- // In R5RS syntax-rules, the initial name is neither a
- // pattern variable or a literal identifier, so ignore it.
- if (pattern instanceof Pair) {
- Pair p = (Pair) pattern;
- programbuf.append((char) ((1 << 3)
- | SyntaxPattern.MATCH_PAIR));
- programbuf.append((char) SyntaxPattern.MATCH_IGNORE);
- pattern = p.getCdr();
- } else {
- // Identifier macro? FIXME
- tr.error('e', "pattern does not start with name");
- return;
- }
- SyntaxPattern spattern =
- new SyntaxPattern(programbuf, pattern, pattern_syntax,
- ellipsis, literal_identifiers, tr);
- this.rules[i] =
- new SyntaxRule(spattern, template,
- template_syntax, ellipsis, tr);
- } finally {
- PatternScope.pop(tr);
- tr.pop();
- }
- } finally {
- tr.setLine(save_filename, save_line, save_column);
- }
- }
- // Calculate maxVars:
- for (int i = this.rules.length; --i >= 0; ) {
- int size = this.rules[i].patternNesting.length();
- if (size > maxVars)
- maxVars = size;
- }
- }
- /* Recursively translate a pattern in a syntax-rule to a Pattern object.
- * @param pattern the the pattern to translate
- * @param literal_identifiers the literals of the syntax-rule
- * @param nesting the depth of ... we are inside
- * @param tr the current Translator
- * @return the translated Pattern
- */
- public Object apply1(Object arg) {
- if (arg instanceof SyntaxForm) {
- SyntaxForm sf = (SyntaxForm) arg;
- Translator tr = (Translator) Compilation.getCurrent();
- ScopeExp save_scope = tr.currentScope();
- tr.setCurrentScope(sf.getScope());
- try {
- return expand(sf, tr);
- } finally {
- tr.setCurrentScope(save_scope);
- }
- } else
- return expand(arg, (Translator) Compilation.getCurrent());
- }
- /* DEBUGGING:
- private void printElement(Object el, StringBuffer sb) {
- if (el instanceof Object[]) {
- Object[] arr = (Object[]) el;
- sb.append('{');
- for (int i = 0; i < arr.length; i++) {
- if (i != 0)
- sb.append(", ");
- printElement(arr[i], sb);
- }
- sb.append('}');
- } else
- sb.append(el);
- }
- END DEBUGGING */
- public Object expand(Object obj, Translator tr) {
- Object[] vars = new Object[maxVars];
- Macro macro = (Macro) tr.getCurrentSyntax();
- /* DEBUGGING:
- System.err.println("match "+macro+" args:"+obj+" maxVars:"+maxVars);
- System.err.flush();
- */
- for (int i = 0; i < rules.length; i++) {
- SyntaxRule rule = rules[i];
- if (rule==null)
- return new ErrorExp("error defining "+macro);
- // check that literals have correct binding - FIXME!!
- Pattern pattern = rule.pattern;
- boolean matched = pattern.match (obj, vars, 0);
- if (matched) {
- if (true) { // DEBUGGING
- /*
- OutPort err = OutPort.errDefault();
- StringBuffer sb = new StringBuffer();
- sb.append("{Expand "+macro + " rule#" + i
- +" - matched variables: ");
- for (int j = 0; j < rule.pattern.varCount; j++) {
- if (j > 0) sb.append("; ");
- sb.append(j); sb.append(": ");
- printElement(vars[j], sb);
- }
- sb.append('}');
- err.println(sb);
- err.flush();
- */
- }
- if (true) {
- /* DEBUGGING:
- OutPort err = OutPort.errDefault();
- err.print("Expanding "); err.println(getName());
- rule.print_template_program(null, err);
- err.flush();
- */
- }
- Object expansion = rule.execute(vars, tr);
- if (false) { // DEBUGGING:
- OutPort err = OutPort.errDefault();
- err.print("{Expansion of ");
- err.print(macro);
- err.println(":");
- err.startLogicalBlock(" ", "}", 2);
- DisplayFormat.schemeWriteFormat.writeObject(expansion, err);
- err.endLogicalBlock("}");
- err.println();
- err.flush();
- }
- return expansion;
- }
- }
- /* DEBUGGING:
- System.err.println("no matching syntax-rule for "
- + getName());
- System.err.flush();
- */
- return tr.syntaxError ("no matching syntax-rule for "
- + getName());
- }
- public void print(Consumer out) {
- out.write("#<macro ");
- ReportFormat.print(getName(), out);
- out.write('>');
- }
- /**
- * @serialData Write literal_identifiers followed by rules,
- * using writeObject.
- */
- public void writeExternal(ObjectOutput out) throws IOException {
- out.writeObject(literal_identifiers);
- out.writeObject(rules);
- out.writeInt(maxVars);
- out.writeObject(getSymbol());
- }
- public void readExternal(ObjectInput in)
- throws IOException, ClassNotFoundException {
- literal_identifiers = (Object[]) in.readObject();
- rules = (SyntaxRule[]) in.readObject();
- maxVars = in.readInt();
- Object name = in.readObject();
- if (name != null)
- setSymbol(name);
- }
- }
|