示例#1
0
 public static Formula parseFormula(string text, ParsedThing parsedThing)
 {
     return new FormulaParser(parsedThing).parse(text);
 }
示例#2
0
 public FormulaParser(ParsedThing parsedThing)
 {
     this.parsedThing = parsedThing;
 }
示例#3
0
 private static GurpsProperty createParsedThing(ParsedThing parsedThing)
 {
     if (parsedThing.subPropertyName != null)
         throw parsedThing.createError("No '.' allowed in names");
     switch (parsedThing.declarationOperator)
     {
         case ":":
             if (skillFormulaRegex.IsMatch(parsedThing.formula))
             {
                 SkillDifficulty difficulty = AbstractSkill.difficultyFromChar(parsedThing.formula[parsedThing.formula.Length - 1]);
                 Formula formula = FormulaParser.parseFormula(parsedThing.formula.Remove(parsedThing.formula.Length - 1), parsedThing);
                 return new Skill(parsedThing, difficulty, formula);
             }
             else
             {
                 Formula costFormula = FormulaParser.parseFormula(parsedThing.formula, parsedThing);
                 if (costFormula.usedNames().Contains("level"))
                     return new IntAdvantage(parsedThing, costFormula);
                 else
                     return new BooleanAdvantage(parsedThing, costFormula);
             }
         case ":=":
             {
                 SkillDifficulty difficulty = SkillDifficulty.Unspecified;
                 string formulaText = parsedThing.formula;
                 if (skillFormulaRegex.IsMatch(parsedThing.formula))
                 {
                     difficulty = AbstractSkill.difficultyFromChar(parsedThing.formula[parsedThing.formula.Length - 1]);
                     formulaText = parsedThing.formula.Remove(parsedThing.formula.Length - 1);
                 }
                 Formula formula = FormulaParser.parseFormula(formulaText, parsedThing);
                 if (!(formula is Formula.Identifier))
                     throw parsedThing.createError("expected name of skill. got '" + formulaText + "'");
                 return new InheritedSkill(parsedThing, difficulty, ((Formula.Identifier)formula).token);
             }
         case "=":
             {
                 Formula formula = FormulaParser.parseFormula(parsedThing.formula, parsedThing);
                 return new AttributeFunction(parsedThing, formula);
             }
         default:
             throw parsedThing.createError("expected ':', '=', or ':='. Got '" + parsedThing.declarationOperator + "'");
     }
 }
示例#4
0
 private static IEnumerable<ParsedThing> parseFile(string path)
 {
     string[] lines = File.ReadAllLines(path);
     for (int i = 0; i < lines.Length; i++)
     {
         string line;
         if (isLineBlank(line = lines[i].Trim()))
             continue;
         Action throwParseError = delegate() { throw new GurpenatorException("syntax problem (" + path + ":" + (i + 1) + ")"); };
         Match match = null;
         // hack for local recursion (for DRY)
         Func<ParsedThing> parseThing = null;
         parseThing = delegate()
         {
             string name = match.Groups[1].Value.Trim();
             string subPropertyName = match.Groups[2].Success ? match.Groups[2].Value.Trim() : null;
             string declarationOperator = match.Groups[3].Value;
             string formula = match.Groups[4].Value.Trim();
             string comment = match.Groups[5].Success ? match.Groups[5].Value.Trim() : null;
             ParsedThing thing = new ParsedThing(name, subPropertyName, declarationOperator, formula, comment, path, i + 1);
             if (reservedWords.Contains(name))
                 throw thing.createError("name '" + name + "' is reserved");
             bool hasOpenBrace = match.Groups[6].Success;
             if (!hasOpenBrace)
                 return thing;
             i++;
             int firstLineIndex = i;
             for (; i < lines.Length; i++)
             {
                 if (isLineBlank(line = lines[i].Trim()))
                     continue;
                 if (line == "}")
                     return thing;
                 if (i == firstLineIndex && (match = commentRegex.Match(line)).Success)
                 {
                     // the first line can be the comment
                     if (thing.comment != null)
                         throwParseError(); // two comments?
                     thing.comment = match.Groups[1].Value;
                     continue;
                 }
                 if ((match = thingStartLineRegex.Match(line)).Success)
                 {
                     thing.subThings.Add(parseThing());
                     continue;
                 }
                 throwParseError();
             }
             throw thing.createError("syntax problem. '{' missing '}'");
         };
         if ((match = thingStartLineRegex.Match(line)).Success)
         {
             yield return parseThing();
             continue;
         }
         throwParseError();
     }
 }
示例#5
0
 public PercentToken(ParsedThing parseThing, decimal value)
     : base(parseThing)
 {
     this.value = value;
 }
示例#6
0
 public InheritedSkill(ParsedThing parsedThing, SkillDifficulty difficultyOverride, IdentifierToken parentSkillToken)
     : base(parsedThing)
 {
     this.difficultyOverride = difficultyOverride;
     this.parentSkillToken = parentSkillToken;
 }
示例#7
0
 protected Effect(GurpsProperty owner, string traitName, Formula formula, ParsedThing parsedThing)
 {
     this.owner = owner;
     this.traitName = traitName;
     this.formula = formula;
     this.parsedThing = parsedThing;
 }
示例#8
0
 public SymbolToken(ParsedThing parseThing, string text)
     : base(parseThing)
 {
     this.text = text;
 }
示例#9
0
 public BooleanAdvantage(ParsedThing parsedThing, Formula costFormula)
     : base(parsedThing, costFormula)
 {
     formattingFunction = intToBoolFormattingFunction;
 }
示例#10
0
 public CostModifier(GurpsProperty owner, string traitName, Formula formula, ParsedThing parsedThing)
     : base(owner, traitName, formula, parsedThing)
 {
 }
示例#11
0
 public Skill(ParsedThing parsedThing, SkillDifficulty difficulty, Formula formula)
     : base(parsedThing)
 {
     this.difficulty = difficulty;
     this.formula = formula;
 }
示例#12
0
 public AttributeFunction(ParsedThing parsedThing, Formula formula)
     : base(parsedThing)
 {
     this.formula = formula;
 }
示例#13
0
 public IntAdvantage(ParsedThing parsedThing, Formula costFormula)
     : base(parsedThing, costFormula)
 {
 }
示例#14
0
 public Token(ParsedThing parseThing)
 {
     this.parseThing = parseThing;
 }
示例#15
0
 protected AbstractSkill(ParsedThing parsedThing)
     : base(parsedThing)
 {
 }
示例#16
0
 public IdentifierToken(ParsedThing parseThing, string text)
     : base(parseThing)
 {
     this.text = text;
 }
示例#17
0
 public Advantage(ParsedThing parsedThing, Formula costFormula)
     : base(parsedThing)
 {
     this.costFormula = costFormula;
 }
示例#18
0
 public IntToken(ParsedThing parseThing, int value)
     : base(parseThing)
 {
     this.value = value;
 }
示例#19
0
 private static GurpsProperty interpretParsedThing(ParsedThing parsedThing)
 {
     GurpsProperty property = createParsedThing(parsedThing);
     foreach (ParsedThing subThing in parsedThing.subThings)
     {
         if (new string[] { "category", "default", "requires" }.Contains(subThing.name))
         {
             if (subThing.subPropertyName != null)
                 throw subThing.createError("property '" + subThing.name + "' has no subproperty '" + subThing.subPropertyName + "'");
             Formula formula = FormulaParser.parseFormula(subThing.formula, subThing);
             switch (subThing.name)
             {
                 case "category":
                     if (!(formula is Formula.BooleanLiteral))
                         throw subThing.createError("categry can only be 'true' or 'false'");
                     if (!(property is AbstractSkill))
                         throw subThing.createError("only skills can be categories");
                     ((AbstractSkill)property).category = ((Formula.BooleanLiteral)formula).value.value;
                     continue;
                 case "default":
                 case "requires":
                     // TODO
                     continue;
             }
             throw null;
         }
         switch (subThing.declarationOperator)
         {
             case "+=":
             case "-=":
                 {
                     string traitName = subThing.name;
                     Formula formula = FormulaParser.parseFormula(subThing.formula, subThing);
                     if (subThing.subPropertyName == null)
                     {
                         if (subThing.declarationOperator == "-=")
                         {
                             // negate the formula
                             formula = new Formula.UnaryPrefix(new SymbolToken(subThing, "-"), formula);
                         }
                         property.effects.Add(new TraitModifier(property, traitName, formula, subThing));
                     }
                     else if (subThing.subPropertyName == "cost")
                         property.effects.Add(new CostModifier(property, traitName, formula, subThing));
                     else
                         throw subThing.createError("can't modify the '" + subThing.subPropertyName + "' of another trait");
                     if (subThing.subThings.Count > 0)
                         throw subThing.subThings[0].createError("Subitems not allowed here");
                     continue;
                 }
             case ":":
                 if (subThing.subPropertyName != null)
                     throw subThing.createError("No '.' allowed in names");
                 // TODO
                 continue;
         }
         throw subThing.createError("illegal operator '" + subThing.declarationOperator + "' for property");
     }
     return property;
 }
示例#20
0
 public BooleanToken(ParsedThing parseThing, bool value)
     : base(parseThing)
 {
     this.value = value;
 }
示例#21
0
 protected GurpsProperty(ParsedThing parsedThing)
 {
     this.parsedThing = parsedThing;
 }