[14744] | 1 | namespace HeuristicLab.Problems.ProgramSynthesis.Push.Parser {
|
---|
| 2 | using System.Collections.Generic;
|
---|
| 3 | using System.Globalization;
|
---|
| 4 |
|
---|
| 5 | using HeuristicLab.Problems.ProgramSynthesis.Push.Expressions;
|
---|
| 6 |
|
---|
| 7 | public static class PushParser {
|
---|
| 8 | private const string openBrace = "(";
|
---|
| 9 |
|
---|
| 10 | private const string closeBrace = ")";
|
---|
| 11 |
|
---|
| 12 | private const char delimiter = ' ';
|
---|
| 13 |
|
---|
| 14 | private static readonly CultureInfo cultureInfo = CultureInfo.CreateSpecificCulture("en-US");
|
---|
| 15 |
|
---|
| 16 | private static readonly char[] symbolTrim = { '\r', '\n' };
|
---|
| 17 |
|
---|
[14777] | 18 | public static Expression Parse(string source, int startIndex = 0) {
|
---|
[14744] | 19 | var symbols = source.Split(delimiter);
|
---|
| 20 |
|
---|
| 21 | int endIndex;
|
---|
| 22 | return Parse(symbols, 0, out endIndex);
|
---|
| 23 | }
|
---|
| 24 |
|
---|
[14777] | 25 | public static PushProgram ParseProgram(string source, int startIndex = 0) {
|
---|
| 26 | var expression = Parse(source, startIndex);
|
---|
| 27 |
|
---|
| 28 | return expression as PushProgram ?? new PushProgram(new[] { expression });
|
---|
| 29 | }
|
---|
| 30 |
|
---|
| 31 | private static Expression Parse(string[] symbols, int startIndex, out int endIndex) {
|
---|
[14744] | 32 | var expressions = new List<Expression>();
|
---|
| 33 |
|
---|
| 34 | for (var i = startIndex; i < symbols.Length; i++) {
|
---|
| 35 | var symbol = symbols[i].TrimEnd(symbolTrim);
|
---|
| 36 |
|
---|
| 37 | if (string.IsNullOrWhiteSpace(symbol)) continue;
|
---|
| 38 |
|
---|
| 39 | switch (symbol) {
|
---|
| 40 | case openBrace:
|
---|
| 41 | var subExpression = Parse(symbols, i + 1, out endIndex);
|
---|
| 42 | expressions.Insert(0, subExpression);
|
---|
| 43 | i = endIndex;
|
---|
| 44 | continue;
|
---|
| 45 | case closeBrace:
|
---|
| 46 | endIndex = i;
|
---|
[14777] | 47 | return new PushProgram(expressions);
|
---|
[14744] | 48 | }
|
---|
| 49 |
|
---|
| 50 | // literal
|
---|
| 51 | Expression expression;
|
---|
| 52 | if (TryParseLiteral(symbol, out expression)) {
|
---|
| 53 | expressions.Insert(0, expression);
|
---|
| 54 | continue;
|
---|
| 55 | }
|
---|
| 56 |
|
---|
| 57 | // expression
|
---|
| 58 | if (ExpressionTable.TryGetStatelessExpression(symbol, out expression)
|
---|
[14777] | 59 | || ExpressionTable.TryGetStatefulExpression(symbol, out expression)) {
|
---|
[14744] | 60 | expressions.Insert(0, expression);
|
---|
| 61 | continue;
|
---|
| 62 | }
|
---|
| 63 |
|
---|
| 64 | // identifier - custom expression or named literals
|
---|
| 65 | expressions.Insert(0, new NameDefineXExecExpression(symbol));
|
---|
| 66 | }
|
---|
| 67 |
|
---|
| 68 | endIndex = symbols.Length - 1;
|
---|
| 69 |
|
---|
[14777] | 70 | switch (expressions.Count) {
|
---|
| 71 | case 0:
|
---|
| 72 | return PushProgram.Empty;
|
---|
| 73 | case 1:
|
---|
| 74 | return expressions[0];
|
---|
| 75 | default:
|
---|
| 76 | return new PushProgram(expressions);
|
---|
| 77 | }
|
---|
[14744] | 78 | }
|
---|
| 79 |
|
---|
| 80 | private static bool TryParseLiteral(string word, out Expression expression) {
|
---|
| 81 | long longValue;
|
---|
| 82 | if (long.TryParse(word, out longValue)) {
|
---|
| 83 | expression = new IntegerPushExpression(longValue);
|
---|
| 84 | return true;
|
---|
| 85 | }
|
---|
| 86 |
|
---|
| 87 | double floatValue;
|
---|
| 88 | if (double.TryParse(word, NumberStyles.Float, cultureInfo, out floatValue)) {
|
---|
| 89 | expression = new FloatPushExpression(floatValue);
|
---|
| 90 | return true;
|
---|
| 91 | }
|
---|
| 92 |
|
---|
| 93 | bool booleanValue;
|
---|
| 94 | if (bool.TryParse(word, out booleanValue)) {
|
---|
| 95 | expression = new BooleanPushExpression(booleanValue);
|
---|
| 96 | return true;
|
---|
| 97 | }
|
---|
| 98 |
|
---|
| 99 | expression = null;
|
---|
| 100 | return false;
|
---|
| 101 | }
|
---|
| 102 | }
|
---|
| 103 | } |
---|