/* DirectiveInstructionParserStage.java (c) 2008-2014 Edward Swartz All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html */ package v9t9.tools.asm; import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import v9t9.common.asm.IInstruction; import v9t9.common.asm.IOperand; import v9t9.tools.asm.directive.AorgDirective; import v9t9.tools.asm.directive.AssertDirective; import v9t9.tools.asm.directive.BssDirective; import v9t9.tools.asm.directive.ConstPoolDirective; import v9t9.tools.asm.directive.DefineByteDirective; import v9t9.tools.asm.directive.DefineWordDirective; import v9t9.tools.asm.directive.Directive; import v9t9.tools.asm.directive.EquDirective; import v9t9.tools.asm.directive.EvenDirective; import v9t9.tools.asm.directive.IgnoreDirective; /** * Parse directives * @author ejs * */ public class DirectiveInstructionParserStage implements IInstructionParserStage { static class DirectiveInfo { int argNum; Class<? extends Directive> klass; public DirectiveInfo(int argNum, Class<? extends Directive> klass) { this.argNum = argNum; this.klass = klass; } } private static final Map<String, DirectiveInfo> dirMap = new HashMap<String, DirectiveInfo>(); private final OperandParser operandParser; static { dirMap.put("aorg", new DirectiveInfo(1, AorgDirective.class)); dirMap.put("equ", new DirectiveInfo(1, EquDirective.class)); dirMap.put("dw", new DirectiveInfo(-1, DefineWordDirective.class)); dirMap.put("data", new DirectiveInfo(-1, DefineWordDirective.class)); dirMap.put("db", new DirectiveInfo(-1, DefineByteDirective.class)); dirMap.put("byte", new DirectiveInfo(-1, DefineByteDirective.class)); dirMap.put("text", new DirectiveInfo(-1, DefineByteDirective.class)); dirMap.put("bss", new DirectiveInfo(1, BssDirective.class)); dirMap.put("even", new DirectiveInfo(0, EvenDirective.class)); dirMap.put("consttable", new DirectiveInfo(0, ConstPoolDirective.class)); dirMap.put("def", new DirectiveInfo(-1, IgnoreDirective.class)); dirMap.put("idt", new DirectiveInfo(-1, IgnoreDirective.class)); dirMap.put("titl", new DirectiveInfo(-1, IgnoreDirective.class)); dirMap.put("end", new DirectiveInfo(0, IgnoreDirective.class)); dirMap.put("rorg", new DirectiveInfo(0, IgnoreDirective.class)); dirMap.put("assert", new DirectiveInfo(1, AssertDirective.class)); } public DirectiveInstructionParserStage(OperandParser operandParser) { this.operandParser = operandParser; } /* (non-Javadoc) * @see v9t9.tools.asm.IInstructionParserStage#parse(java.lang.String) */ public IInstruction[] parse(String descr, String string) throws ParseException { AssemblerTokenizer tokenizer = new AssemblerTokenizer(string); tokenizer.match(AssemblerTokenizer.ID); String dir = tokenizer.currentToken().toLowerCase(); DirectiveInfo info = dirMap.get(dir); if (info == null) return null; int cnt = info.argNum; List<IOperand> ops = new ArrayList<IOperand>(); while (cnt != 0) { try { IOperand op = operandParser.parse(tokenizer); ops.add(op); if (cnt > 0) { cnt--; if (cnt == 0) break; } int t = tokenizer.nextToken(); if (t == AssemblerTokenizer.EOF) { if (cnt > 0) throw new ParseException("Expected additional arguments"); break; } else if (t != ',') { if (cnt > 0) { throw new ParseException("Expected ','"); } // assume comment tokenizer.skipToEOF(); break; } } catch (ParseException e) { if (e.getMessage().contains("Unexpected end of line") && cnt < 0) { // assume comment tokenizer.skipToEOF(); break; } else { throw e; } } } if (tokenizer.nextToken() != AssemblerTokenizer.EOF) { if (cnt < 0) { throw new ParseException("Trailing garbage: " + tokenizer.currentToken()); } else { // assume comment tokenizer.skipToEOF(); } } try { Constructor<? extends Directive> constructor = info.klass.getConstructor( List.class); Directive directive = constructor.newInstance(ops); return new IInstruction[] { directive }; } catch (Exception e) { throw (IllegalStateException) new IllegalStateException().initCause(e); } } }