package cn.bran.japid.compiler; import japa.parser.ast.body.Parameter; import java.util.List; import cn.bran.japid.util.StringUtils; /** * parse `tag (t, v) | U u * * @author Bing Ran<bing_ran@hotmail.com> * */ public class TagInvocationLineParser { /** * TODO: use stricter syntax checker. The callback border symbol is not * strictly picked up based on Java grammar, etc. * * @param line * @return */ public Tag parse(String line) { // String original = line; Tag tag = new Tag(); // get tag name for (int i = 0; i < line.length(); i++) { char c = line.charAt(i); if (Character.isJavaIdentifierPart(c) || c == '.' || c == '/') { continue; } else { if (Character.isWhitespace(c) || c == '(' || c == '|') { tag.tagName = line.substring(0, i).replace('/', '.'); if (tag.tagName.startsWith("..")) tag.tagName = tag.tagName.substring(1); line = line.substring(i).trim(); break; } else { throw new RuntimeException("invalid character in the tag invocation line " + line + ": [" + c + "]"); } } } if (tag.tagName == null) { // there was no end char in the line. so the whole line is the tag // name tag.tagName = line.replace('/', '.'); return tag; } if (tag.tagName.equals("def")) { tag = new Tag.TagDef(); if (!line.endsWith(")")) line += "()"; JavaSyntaxTool.isValidMethDecl(line); tag.args = line; return tag; } else if (tag.tagName.equals("set")) { tag = new Tag.TagSet(); tag.args = line; return tag; } else if (tag.tagName.equals("get")) { tag.args = line; return tag; } // let's parse the closure params int vertline = line.lastIndexOf('|'); if (vertline < 0) { List<String> args = JavaSyntaxTool.parseArgs(line); tag.args = StringUtils.join(args, ","); parseNamedArgs(tag); } else { // need to find out the real meaning of the vertical bar String left = line.substring(0, vertline); String right = line.substring(vertline); if (right.length() > 1) right = right.substring(1); else right = ""; if (JavaSyntaxTool.isValidParamList(right)) parseTagCallWithCallback(line, tag); else // the bar may be part of a argument { List<String> args = JavaSyntaxTool.parseArgs(line); tag.args = StringUtils.join(args, ","); parseNamedArgs(tag); } } if ("Each".equals(tag.tagName) || "each".equals(tag.tagName)) { if (!tag.hasBody) { throw new RuntimeException("The Each tag must have a body. Invalid statement: " + line); } } return tag; } private void parseTagCallWithCallback(String line, Tag tag) { int vertline = line.lastIndexOf('|'); if (vertline >= 0) { String closureArgs = line.substring(vertline + 1).trim(); // test syntax JavaSyntaxTool.parseParams(closureArgs); tag.callbackArgs = closureArgs; tag.hasBody = true; line = line.substring(0, vertline).trim(); if (line.length() == 0) return; else { // parse args. char firstC = line.charAt(0); char lastC = line.charAt(line.length() - 1); if ('(' == firstC) { if (')' != lastC) { throw new RuntimeException("The tag argument part is not valid: parenthesis is not paired."); } else { tag.args = line.substring(1, line.length() - 1); } } else { tag.args = line; } parseNamedArgs(tag); } } else throw new RuntimeException("tag args not valid: " + line); } private void parseNamedArgs(Tag tag) { // check for grammar and named arguments List<NamedArg> args = JavaSyntaxTool.parseNamedArgs(tag.args); if (args.size() > 0) { tag.namedArgs = args; // let reformat the args to named("a1", a), named("a2", 12), etc String ar = ""; for (NamedArg na : args) { ar += na.toNamed() + ", "; } if (ar.endsWith(", ")) { ar = ar.substring(0, ar.length() - 2); } tag.args = ar; } } }