Search in sources :

Example 26 with FHIRLexerException

use of org.hl7.fhir.r5.utils.FHIRLexer.FHIRLexerException in project org.hl7.fhir.core by hapifhir.

the class FHIRPathEngine method parseExpression.

private ExpressionNode parseExpression(FHIRLexer lexer, boolean proximal) throws FHIRLexerException {
    ExpressionNode result = new ExpressionNode(lexer.nextId());
    ExpressionNode wrapper = null;
    SourceLocation c = lexer.getCurrentStartLocation();
    result.setStart(lexer.getCurrentLocation());
    // so we back correct for both +/- and as part of a numeric constant below.
    if (Utilities.existsInList(lexer.getCurrent(), "-", "+")) {
        wrapper = new ExpressionNode(lexer.nextId());
        wrapper.setKind(Kind.Unary);
        wrapper.setOperation(ExpressionNode.Operation.fromCode(lexer.take()));
        wrapper.setProximal(proximal);
    }
    if (lexer.isConstant()) {
        boolean isString = lexer.isStringConstant();
        if (!isString && (lexer.getCurrent().startsWith("-") || lexer.getCurrent().startsWith("+"))) {
            // the grammar says that this is a unary operation; it affects the correct processing order of the inner operations
            wrapper = new ExpressionNode(lexer.nextId());
            wrapper.setKind(Kind.Unary);
            wrapper.setOperation(ExpressionNode.Operation.fromCode(lexer.getCurrent().substring(0, 1)));
            wrapper.setProximal(proximal);
            lexer.setCurrent(lexer.getCurrent().substring(1));
        }
        result.setConstant(processConstant(lexer));
        result.setKind(Kind.Constant);
        if (!isString && !lexer.done() && (result.getConstant() instanceof IntegerType || result.getConstant() instanceof DecimalType) && (lexer.isStringConstant() || lexer.hasToken("year", "years", "month", "months", "week", "weeks", "day", "days", "hour", "hours", "minute", "minutes", "second", "seconds", "millisecond", "milliseconds"))) {
            // it's a quantity
            String ucum = null;
            if (lexer.hasToken("year", "years", "month", "months", "week", "weeks", "day", "days", "hour", "hours", "minute", "minutes", "second", "seconds", "millisecond", "milliseconds")) {
                String s = lexer.take();
                if (s.equals("year") || s.equals("years"))
                    ucum = "a";
                else if (s.equals("month") || s.equals("months"))
                    ucum = "mo";
                else if (s.equals("week") || s.equals("weeks"))
                    ucum = "wk";
                else if (s.equals("day") || s.equals("days"))
                    ucum = "d";
                else if (s.equals("hour") || s.equals("hours"))
                    ucum = "h";
                else if (s.equals("minute") || s.equals("minutes"))
                    ucum = "min";
                else if (s.equals("second") || s.equals("seconds"))
                    ucum = "s";
                else
                    // (s.equals("millisecond") || s.equals("milliseconds"))
                    ucum = "ms";
            } else
                ucum = lexer.readConstant("units");
            result.setConstant(new Quantity().setValue(new BigDecimal(result.getConstant().primitiveValue())).setSystem("http://unitsofmeasure.org").setCode(ucum));
        }
        result.setEnd(lexer.getCurrentLocation());
    } else if ("(".equals(lexer.getCurrent())) {
        lexer.next();
        result.setKind(Kind.Group);
        result.setGroup(parseExpression(lexer, true));
        if (!")".equals(lexer.getCurrent()))
            throw lexer.error("Found " + lexer.getCurrent() + " expecting a \")\"");
        result.setEnd(lexer.getCurrentLocation());
        lexer.next();
    } else {
        if (!lexer.isToken() && !lexer.getCurrent().startsWith("`"))
            throw lexer.error("Found " + lexer.getCurrent() + " expecting a token name");
        if (lexer.isFixedName())
            result.setName(lexer.readFixedName("Path Name"));
        else
            result.setName(lexer.take());
        result.setEnd(lexer.getCurrentLocation());
        if (!result.checkName())
            throw lexer.error("Found " + result.getName() + " expecting a valid token name");
        if ("(".equals(lexer.getCurrent())) {
            Function f = Function.fromCode(result.getName());
            FunctionDetails details = null;
            if (f == null) {
                if (hostServices != null)
                    details = hostServices.resolveFunction(result.getName());
                if (details == null)
                    throw lexer.error("The name " + result.getName() + " is not a valid function name");
                f = Function.Custom;
            }
            result.setKind(Kind.Function);
            result.setFunction(f);
            lexer.next();
            while (!")".equals(lexer.getCurrent())) {
                result.getParameters().add(parseExpression(lexer, true));
                if (",".equals(lexer.getCurrent()))
                    lexer.next();
                else if (!")".equals(lexer.getCurrent()))
                    throw lexer.error("The token " + lexer.getCurrent() + " is not expected here - either a \",\" or a \")\" expected");
            }
            result.setEnd(lexer.getCurrentLocation());
            lexer.next();
            checkParameters(lexer, c, result, details);
        } else
            result.setKind(Kind.Name);
    }
    ExpressionNode focus = result;
    if ("[".equals(lexer.getCurrent())) {
        lexer.next();
        ExpressionNode item = new ExpressionNode(lexer.nextId());
        item.setKind(Kind.Function);
        item.setFunction(ExpressionNode.Function.Item);
        item.getParameters().add(parseExpression(lexer, true));
        if (!lexer.getCurrent().equals("]"))
            throw lexer.error("The token " + lexer.getCurrent() + " is not expected here - a \"]\" expected");
        lexer.next();
        result.setInner(item);
        focus = item;
    }
    if (".".equals(lexer.getCurrent())) {
        lexer.next();
        focus.setInner(parseExpression(lexer, false));
    }
    result.setProximal(proximal);
    if (proximal) {
        while (lexer.isOp()) {
            focus.setOperation(ExpressionNode.Operation.fromCode(lexer.getCurrent()));
            focus.setOpStart(lexer.getCurrentStartLocation());
            focus.setOpEnd(lexer.getCurrentLocation());
            lexer.next();
            focus.setOpNext(parseExpression(lexer, false));
            focus = focus.getOpNext();
        }
        result = organisePrecedence(lexer, result);
    }
    if (wrapper != null) {
        wrapper.setOpNext(result);
        result.setProximal(false);
        result = wrapper;
    }
    return result;
}
Also used : SourceLocation(org.hl7.fhir.utilities.SourceLocation) FunctionDetails(org.hl7.fhir.r4.utils.FHIRPathEngine.IEvaluationContext.FunctionDetails) ExpressionNode(org.hl7.fhir.r4.model.ExpressionNode) BigDecimal(java.math.BigDecimal)

Example 27 with FHIRLexerException

use of org.hl7.fhir.r5.utils.FHIRLexer.FHIRLexerException in project org.hl7.fhir.core by hapifhir.

the class FHIRPathEngine method parseExpression.

private ExpressionNode parseExpression(FHIRLexer lexer, boolean proximal) throws FHIRLexerException {
    ExpressionNode result = new ExpressionNode(lexer.nextId());
    ExpressionNode wrapper = null;
    SourceLocation c = lexer.getCurrentStartLocation();
    result.setStart(lexer.getCurrentLocation());
    // so we back correct for both +/- and as part of a numeric constant below.
    if (Utilities.existsInList(lexer.getCurrent(), "-", "+")) {
        wrapper = new ExpressionNode(lexer.nextId());
        wrapper.setKind(Kind.Unary);
        wrapper.setOperation(ExpressionNode.Operation.fromCode(lexer.take()));
        wrapper.setStart(lexer.getCurrentLocation());
        wrapper.setProximal(proximal);
    }
    if (lexer.getCurrent() == null) {
        throw lexer.error("Expression terminated unexpectedly");
    } else if (lexer.isConstant()) {
        boolean isString = lexer.isStringConstant();
        if (!isString && (lexer.getCurrent().startsWith("-") || lexer.getCurrent().startsWith("+"))) {
            // the grammar says that this is a unary operation; it affects the correct processing order of the inner operations
            wrapper = new ExpressionNode(lexer.nextId());
            wrapper.setKind(Kind.Unary);
            wrapper.setOperation(ExpressionNode.Operation.fromCode(lexer.getCurrent().substring(0, 1)));
            wrapper.setProximal(proximal);
            wrapper.setStart(lexer.getCurrentLocation());
            lexer.setCurrent(lexer.getCurrent().substring(1));
        }
        result.setConstant(processConstant(lexer));
        result.setKind(Kind.Constant);
        if (!isString && !lexer.done() && (result.getConstant() instanceof IntegerType || result.getConstant() instanceof DecimalType) && (lexer.isStringConstant() || lexer.hasToken("year", "years", "month", "months", "week", "weeks", "day", "days", "hour", "hours", "minute", "minutes", "second", "seconds", "millisecond", "milliseconds"))) {
            // it's a quantity
            String ucum = null;
            String unit = null;
            if (lexer.hasToken("year", "years", "month", "months", "week", "weeks", "day", "days", "hour", "hours", "minute", "minutes", "second", "seconds", "millisecond", "milliseconds")) {
                String s = lexer.take();
                unit = s;
                if (s.equals("year") || s.equals("years")) {
                // this is not the UCUM year
                } else if (s.equals("month") || s.equals("months")) {
                // this is not the UCUM month
                } else if (s.equals("week") || s.equals("weeks")) {
                    ucum = "wk";
                } else if (s.equals("day") || s.equals("days")) {
                    ucum = "d";
                } else if (s.equals("hour") || s.equals("hours")) {
                    ucum = "h";
                } else if (s.equals("minute") || s.equals("minutes")) {
                    ucum = "min";
                } else if (s.equals("second") || s.equals("seconds")) {
                    ucum = "s";
                } else {
                    // (s.equals("millisecond") || s.equals("milliseconds"))
                    ucum = "ms";
                }
            } else {
                ucum = lexer.readConstant("units");
            }
            result.setConstant(new Quantity().setValue(new BigDecimal(result.getConstant().primitiveValue())).setUnit(unit).setSystem(ucum == null ? null : "http://unitsofmeasure.org").setCode(ucum));
        }
        result.setEnd(lexer.getCurrentLocation());
    } else if ("(".equals(lexer.getCurrent())) {
        lexer.next();
        result.setKind(Kind.Group);
        result.setGroup(parseExpression(lexer, true));
        if (!")".equals(lexer.getCurrent())) {
            throw lexer.error("Found " + lexer.getCurrent() + " expecting a \")\"");
        }
        result.setEnd(lexer.getCurrentLocation());
        lexer.next();
    } else {
        if (!lexer.isToken() && !lexer.getCurrent().startsWith("`")) {
            throw lexer.error("Found " + lexer.getCurrent() + " expecting a token name");
        }
        if (lexer.isFixedName()) {
            result.setName(lexer.readFixedName("Path Name"));
        } else {
            result.setName(lexer.take());
        }
        result.setEnd(lexer.getCurrentLocation());
        if (!result.checkName()) {
            throw lexer.error("Found " + result.getName() + " expecting a valid token name");
        }
        if ("(".equals(lexer.getCurrent())) {
            Function f = Function.fromCode(result.getName());
            FunctionDetails details = null;
            if (f == null) {
                if (hostServices != null) {
                    details = hostServices.resolveFunction(result.getName());
                }
                if (details == null) {
                    throw lexer.error("The name " + result.getName() + " is not a valid function name");
                }
                f = Function.Custom;
            }
            result.setKind(Kind.Function);
            result.setFunction(f);
            lexer.next();
            while (!")".equals(lexer.getCurrent())) {
                result.getParameters().add(parseExpression(lexer, true));
                if (",".equals(lexer.getCurrent())) {
                    lexer.next();
                } else if (!")".equals(lexer.getCurrent())) {
                    throw lexer.error("The token " + lexer.getCurrent() + " is not expected here - either a \",\" or a \")\" expected");
                }
            }
            result.setEnd(lexer.getCurrentLocation());
            lexer.next();
            checkParameters(lexer, c, result, details);
        } else {
            result.setKind(Kind.Name);
        }
    }
    ExpressionNode focus = result;
    if ("[".equals(lexer.getCurrent())) {
        lexer.next();
        ExpressionNode item = new ExpressionNode(lexer.nextId());
        item.setKind(Kind.Function);
        item.setFunction(ExpressionNode.Function.Item);
        item.getParameters().add(parseExpression(lexer, true));
        if (!lexer.getCurrent().equals("]")) {
            throw lexer.error("The token " + lexer.getCurrent() + " is not expected here - a \"]\" expected");
        }
        lexer.next();
        result.setInner(item);
        focus = item;
    }
    if (".".equals(lexer.getCurrent())) {
        lexer.next();
        focus.setInner(parseExpression(lexer, false));
    }
    result.setProximal(proximal);
    if (proximal) {
        while (lexer.isOp()) {
            focus.setOperation(ExpressionNode.Operation.fromCode(lexer.getCurrent()));
            focus.setOpStart(lexer.getCurrentStartLocation());
            focus.setOpEnd(lexer.getCurrentLocation());
            lexer.next();
            focus.setOpNext(parseExpression(lexer, false));
            focus = focus.getOpNext();
        }
        result = organisePrecedence(lexer, result);
    }
    if (wrapper != null) {
        wrapper.setOpNext(result);
        result.setProximal(false);
        result = wrapper;
    }
    return result;
}
Also used : SourceLocation(org.hl7.fhir.utilities.SourceLocation) IntegerType(org.hl7.fhir.r5.model.IntegerType) Function(org.hl7.fhir.r5.model.ExpressionNode.Function) FunctionDetails(org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext.FunctionDetails) ExpressionNode(org.hl7.fhir.r5.model.ExpressionNode) DecimalType(org.hl7.fhir.r5.model.DecimalType) Quantity(org.hl7.fhir.r5.model.Quantity) BigDecimal(java.math.BigDecimal)

Example 28 with FHIRLexerException

use of org.hl7.fhir.r5.utils.FHIRLexer.FHIRLexerException in project org.hl7.fhir.core by hapifhir.

the class FHIRPathEngine method parse.

public ExpressionNode parse(String path, String name) throws FHIRLexerException {
    FHIRLexer lexer = new FHIRLexer(path, name);
    if (lexer.done()) {
        throw lexer.error("Path cannot be empty");
    }
    ExpressionNode result = parseExpression(lexer, true);
    if (!lexer.done()) {
        throw lexer.error("Premature ExpressionNode termination at unexpected token \"" + lexer.getCurrent() + "\"");
    }
    result.check();
    return result;
}
Also used : ExpressionNode(org.hl7.fhir.r5.model.ExpressionNode)

Example 29 with FHIRLexerException

use of org.hl7.fhir.r5.utils.FHIRLexer.FHIRLexerException in project org.hl7.fhir.core by hapifhir.

the class FHIRPathEngine method parse.

/**
 * Parse a path that is part of some other syntax
 *
 * @return
 * @throws PathEngineException
 * @throws Exception
 */
public ExpressionNode parse(FHIRLexer lexer) throws FHIRLexerException {
    ExpressionNode result = parseExpression(lexer, true);
    result.check();
    return result;
}
Also used : ExpressionNode(org.hl7.fhir.r5.model.ExpressionNode)

Example 30 with FHIRLexerException

use of org.hl7.fhir.r5.utils.FHIRLexer.FHIRLexerException in project org.hl7.fhir.core by hapifhir.

the class FHIRLexer method processConstant.

public String processConstant(String s) throws FHIRLexerException {
    StringBuilder b = new StringBuilder();
    int i = 1;
    while (i < s.length() - 1) {
        char ch = s.charAt(i);
        if (ch == '\\') {
            i++;
            switch(s.charAt(i)) {
                case 't':
                    b.append('\t');
                    break;
                case 'r':
                    b.append('\r');
                    break;
                case 'n':
                    b.append('\n');
                    break;
                case 'f':
                    b.append('\f');
                    break;
                case '\'':
                    b.append('\'');
                    break;
                case '"':
                    b.append('"');
                    break;
                case '`':
                    b.append('`');
                    break;
                case '\\':
                    b.append('\\');
                    break;
                case '/':
                    b.append('/');
                    break;
                case 'u':
                    i++;
                    int uc = Integer.parseInt(s.substring(i, i + 4), 16);
                    b.append((char) uc);
                    i = i + 4;
                    break;
                default:
                    throw new FHIRLexerException("Unknown character escape \\" + s.charAt(i));
            }
        } else {
            b.append(ch);
            i++;
        }
    }
    return b.toString();
}
Also used : CommaSeparatedStringBuilder(org.hl7.fhir.utilities.CommaSeparatedStringBuilder)

Aggregations

CommaSeparatedStringBuilder (org.hl7.fhir.utilities.CommaSeparatedStringBuilder)9 ExpressionNode (org.hl7.fhir.r5.model.ExpressionNode)6 ExpressionNode (org.hl7.fhir.dstu2.model.ExpressionNode)5 ExpressionNode (org.hl7.fhir.r4.model.ExpressionNode)4 ExpressionNode (org.hl7.fhir.r4b.model.ExpressionNode)4 BigDecimal (java.math.BigDecimal)3 ArrayList (java.util.ArrayList)3 HashMap (java.util.HashMap)3 ExpressionNode (org.hl7.fhir.dstu2016may.model.ExpressionNode)3 ExpressionNode (org.hl7.fhir.dstu3.model.ExpressionNode)3 PathEngineException (org.hl7.fhir.exceptions.PathEngineException)3 SourceLocation (org.hl7.fhir.utilities.SourceLocation)3 Base (org.hl7.fhir.dstu2.model.Base)2 DefinitionException (org.hl7.fhir.exceptions.DefinitionException)2 FHIRException (org.hl7.fhir.exceptions.FHIRException)2 IOException (java.io.IOException)1 HashSet (java.util.HashSet)1 List (java.util.List)1 NotImplementedException (org.apache.commons.lang3.NotImplementedException)1 TypeRefComponent (org.hl7.fhir.dstu2.model.ElementDefinition.TypeRefComponent)1