import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CommonTokenStream;
-import org.antlr.runtime.RecognitionException;
-import org.antlr.runtime.tree.Tree;
import org.xerial.core.XerialError;
import org.xerial.core.XerialErrorCode;
import org.xerial.core.XerialException;
import org.xerial.silk.impl.SilkDataLine;
+import org.xerial.silk.impl.SilkElement;
import org.xerial.silk.impl.SilkFunction;
import org.xerial.silk.impl.SilkLexer;
import org.xerial.silk.impl.SilkNode;
+import org.xerial.silk.impl.SilkNodeParser;
import org.xerial.silk.impl.SilkParser;
import org.xerial.silk.impl.SilkPreamble;
-import org.xerial.silk.impl.SilkParser.silkNode_return;
import org.xerial.util.StringUtil;
import org.xerial.util.antlr.ANTLRUtil;
-import org.xerial.util.bean.impl.BeanUtilImpl;
import org.xerial.util.log.Logger;
/**
// 60,000 lines/sec (SilkPushParser after consuming the lexer input)
// 17000 lines/sec
- silkNode_return ret = parser.silkNode();
- Tree t = (Tree) ret.getTree();
- // 8500 -> 12000 lines/sec
-
- switch (t.getType())
- {
- case SilkParser.Function:
+ try
{
- SilkFunction func = BeanUtilImpl.createBeanFromParseTree(SilkFunction.class, t,
- SilkParser.tokenNames);
- push(new SilkEvent(SilkEventType.FUNCTION, func));
- continue;
+ SilkNodeParser nodeParser = new SilkNodeParser(tokenStream);
+ SilkElement elem = nodeParser.parse();
+ if (elem instanceof SilkNode)
+ push(new SilkEvent(SilkEventType.NODE, (SilkNode) elem));
+ else if (elem instanceof SilkFunction)
+ push(new SilkEvent(SilkEventType.FUNCTION, (SilkFunction) elem));
+
}
- case SilkParser.SilkNode:
+ catch (XerialException e)
{
- SilkNode node = BeanUtilImpl.populateBeanWithParseTree(new SilkNode(), t, SilkParser.tokenNames);
- //SilkNode node = Lens.loadANTLRParseTree(SilkNode.class, t, SilkParser.tokenNames);
- push(new SilkEvent(SilkEventType.NODE, node));
- continue;
- }
- default:
- throw new XerialError(XerialErrorCode.INVALID_INPUT, String.format(
- "line=%d: invalid data type: %s", lineCount, parser.getTokenNames()[t.getType()]));
+ if (e.getErrorCode() == XerialErrorCode.PARSE_ERROR)
+ {
+ // only report warning message
+ _logger.warn(String.format("parse error at line=%d: %s", lineCount, e));
+ }
+ else
+ throw e;
}
- // 17,000 lines/sec (SilkPushParser)
+ continue;
+
+ // 50,000 lines/sec (SilkPushParser when using recursive descent parser)
+
+ // 17,000 lines/sec (SilkPushParser when using ANTLR parser)
// 1500 lines/sec
}
// EOF
push(EOFEvent);
}
- catch (RecognitionException e)
- {
- throw new XerialException(XerialErrorCode.INVALID_INPUT, String.format("parse error line=%d: %s",
- lineCount, e.getMessage()));
- }
+ // catch (RecognitionException e)
+ // {
+ // throw new XerialException(XerialErrorCode.INVALID_INPUT, String.format("parse error line=%d: %s",
+ // lineCount, e.getMessage()));
+ // }
catch (IOException e)
{
throw new XerialException(XerialErrorCode.IO_EXCEPTION, String.format("line=%d: %s", lineCount, e
import org.xerial.util.StringUtil;
/**
- *
+ * Recursive descent parser for {@link SilkNode} and {@link SilkFunction}
*
* @author leo
*
switch (tokenStream.LA(1))
{
case NodeIndent:
- return parseSilkNode();
+ if (tokenStream.LA(2) == At)
+ return parseFunction();
+ else
+ return parseSilkNode();
case FunctionIndent:
SilkFunction func = parseFunction();
return func;
switch (tokenStream.LA(1))
{
case LParen:
+ consume();
parseAttributeList(node);
+ testAndConsume(RParen);
break;
default:
{
switch (nextToken)
{
case At:
- SilkFunction func = parseFunctionInternal();
+ SilkFunction func = parseFunctionInternal(new SilkFunction());
node.setFunction(func);
break;
case PlainOneLine:
break;
}
default:
- throw unexpectedToken(tokenStream.LT(1));
+ throw unexpectedToken(tokenStream.LT(1), At, PlainOneLine, String, JSON);
}
}
- private SilkFunction parseFunctionInternal()
+ private String parseNodeValue() throws XerialException
{
- // TODO
- return null;
+ int nextToken = tokenStream.LA(1);
+
+ switch (nextToken)
+ {
+ case At:
+ // TODO
+ throw new XerialException(XerialErrorCode.PARSE_ERROR, "nested function is not yet supported");
+ case PlainOneLine:
+ case String:
+ case JSON:
+ {
+ Token t = getToken(1);
+ consume();
+ return t.getText();
+ }
+ default:
+ throw unexpectedToken(tokenStream.LT(1), At, PlainOneLine, String, JSON);
+ }
+
}
private void parsePlural(SilkNode node)
case PlainOneLine:
case String:
consume();
- return t.getText();
+ return t.getText().trim();
default:
throw unexpectedToken(t, PlainOneLine, String);
}
}
- private SilkFunction parseFunction()
+ private SilkFunction parseFunction() throws XerialException
{
- return null;
+ SilkFunction func = new SilkFunction();
+ switch (tokenStream.LA(1))
+ {
+ case NodeIndent:
+ {
+ Token t = getToken(1);
+ func.setNodeIndent(t.getText());
+ consume();
+ parseFunctionInternal(func);
+ return func;
+ }
+ case FunctionIndent:
+ {
+ Token t = getToken(1); // function indent
+ func.setNodeIndent(t.getText());
+ consume();
+
+ Token funcName = testAndConsume(PlainOneLine);
+ func.setName(funcName.getText().trim());
+
+ parseFunctionArgs(func);
+
+ return func;
+ }
+ default:
+
+ throw unexpectedToken(tokenStream.LT(1), NodeIndent, FunctionIndent);
+ }
+
+ }
+
+ private void parseFunctionArgs(SilkFunction func) throws XerialException
+ {
+ testAndConsume(LParen);
+ if (!nextTokenIs(RParen))
+ {
+ parseFunctionArg(func);
+ while (nextTokenIs(Comma))
+ {
+ consume();
+ parseFunctionArg(func);
+ }
+ }
+
+ testAndConsume(RParen);
+
+ }
+
+ private void parseFunctionArg(SilkFunction func) throws XerialException
+ {
+ if (nextTokenIs(String) || nextTokenIs(PlainOneLine))
+ {
+ if (tokenStream.LA(2) == Colon)
+ {
+ Token key = getToken(1);
+ consume();
+ consume();
+ String value = parseNodeValue();
+ func.addKeyAndValue(key.getText().trim(), value.trim());
+ return;
+ }
+ }
+
+ String value = parseNodeValue();
+ func.addArgument(value);
+ }
+
+ private SilkFunction parseFunctionInternal(SilkFunction func) throws XerialException
+ {
+ testAndConsume(At);
+ Token funcName = testAndConsume(PlainOneLine);
+ func.setName(funcName.getText().trim());
+
+ parseFunctionArgs(func);
+
+ return func;
}
private XerialException unexpectedToken(Token t) throws XerialException