All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.petitparser.grammar.smalltalk.SmalltalkDefinition Maven / Gradle / Ivy

The newest version!
package org.petitparser.grammar.smalltalk;

import org.petitparser.parser.Parser;
import org.petitparser.parser.primitive.EpsilonParser;
import org.petitparser.tools.GrammarDefinition;

import static org.petitparser.parser.primitive.CharacterParser.any;
import static org.petitparser.parser.primitive.CharacterParser.digit;
import static org.petitparser.parser.primitive.CharacterParser.of;
import static org.petitparser.parser.primitive.CharacterParser.pattern;
import static org.petitparser.parser.primitive.CharacterParser.whitespace;
import static org.petitparser.parser.primitive.CharacterParser.word;
import static org.petitparser.parser.primitive.StringParser.of;

/**
 * Smalltalk grammar definition.
 */
public class SmalltalkDefinition extends GrammarDefinition {

  public SmalltalkDefinition() {
    other();
    number();
    smalltalk();
  }

  private void other() {
    // the original implementation uses a handwritten parser to
    // efficiently consume whitespace and comments
    def("whitespace", whitespace()
        .or(ref("comment")));
    def("comment", of('"')
        .seq(any().starLazy(of('"')))
        .seq(of('"')));
  }

  private void number() {
    // the original implementation uses the hand written number
    // parser of the system, this is the spec of the ANSI standard
    def("number", of('-').optional()
        .seq(ref("positiveNumber")));
    def("positiveNumber", ref("scaledDecimal")
        .or(ref("float"))
        .or(ref("integer")));

    def("integer", ref("radixInteger")
        .or(ref("decimalInteger")));
    def("decimalInteger", ref("digits"));
    def("digits", digit().plus());
    def("radixInteger", ref("radixSpecifier")
        .seq(of('r'))
        .seq(ref("radixDigits")));
    def("radixSpecifier", ref("digits"));
    def("radixDigits", pattern("0-9A-Z").plus());

    def("float", ref("mantissa")
        .seq(ref("exponentLetter")
            .seq(ref("exponent"))
            .optional()));
    def("mantissa", ref("digits")
        .seq(of('.'))
        .seq(ref("digits")));
    def("exponent", of('-')
        .seq(ref("decimalInteger")));
    def("exponentLetter", pattern("edq"));

    def("scaledDecimal", ref("scaledMantissa")
        .seq(of('s'))
        .seq(ref("fractionalDigits").optional()));
    def("scaledMantissa", ref("decimalInteger")
        .or(ref("mantissa")));
    def("fractionalDigits", ref("decimalInteger"));
  }

  private Parser token(Object input) {
    Parser parser;
    if (input instanceof Parser) {
      parser = (Parser) input;
    } else if (input instanceof Character) {
      parser = of((Character) input);
    } else if (input instanceof String) {
      parser = of((String) input);
    } else {
      throw new IllegalStateException("Object not parsable: " + input);
    }
    return parser.token().trim(ref("whitespace"));
  }

  void smalltalk() {
    def("array", token("{")
        .seq(ref("expression").separatedBy(ref("periodToken"))
            .seq(ref("periodToken").optional()).optional())
        .seq(token("}")));
    def("arrayItem", ref("literal")
        .or(ref("symbolLiteralArray"))
        .or(ref("arrayLiteralArray"))
        .or(ref("byteLiteralArray")));
    def("arrayLiteral", token("#(")
        .seq(ref("arrayItem").star())
        .seq(token(")")));
    def("arrayLiteralArray", token("(")
        .seq(ref("arrayItem").star())
        .seq(token(")")));
    def("assignment", ref("variable")
        .seq(ref("assignmentToken")));
    def("assignmentToken", token(":="));
    def("binary", pattern("!%&*+,-/<=>?@\\|~").plus());
    def("binaryExpression", ref("unaryExpression")
        .seq(ref("binaryMessage").star()));
    def("binaryMessage", ref("binaryToken")
        .seq(ref("unaryExpression")));
    def("binaryMethod", ref("binaryToken")
        .seq(ref("variable")));
    def("binaryPragma", ref("binaryToken")
        .seq(ref("arrayItem")));
    def("binaryToken", token(ref("binary")));
    def("block", token("[")
        .seq(ref("blockBody"))
        .seq(token("]")));
    def("blockArgument", token(":")
        .seq(ref("variable")));
    def("blockArguments", ref("blockArgumentsWith")
        .or(ref("blockArgumentsWithout")));
    def("blockArgumentsWith", ref("blockArgument").plus()
        .seq(token("|").or(token("]").and())));
    def("blockArgumentsWithout", new EpsilonParser());
    def("blockBody", ref("blockArguments")
        .seq(ref("sequence")));
    def("byteLiteral", token("#[")
        .seq(ref("numberLiteral").star())
        .seq(token("]")));
    def("byteLiteralArray", token("[")
        .seq(ref("numberLiteral").star())
        .seq(token("]")));
    def("cascadeExpression", ref("keywordExpression")
        .seq(ref("cascadeMessage").star()));
    def("cascadeMessage", token(";")
        .seq(ref("message")));
    def("char", of('$').seq(any()));
    def("charLiteral", ref("charToken"));
    def("charToken", token(ref("char")));
    def("expression", ref("assignment").star()
        .seq(ref("cascadeExpression")));
    def("falseLiteral", ref("falseToken"));
    def("falseToken", token("false")
        .seq(word().not()));
    def("identifier", pattern("a-zA-Z_")
        .seq(pattern("a-zA-Z0-9_").star()));
    def("identifierToken", token(ref("identifier")));
    def("keyword", ref("identifier")
        .seq(of(':')));
    def("keywordExpression", ref("binaryExpression")
        .seq(ref("keywordMessage").optional()));
    def("keywordMessage", ref("keywordToken")
        .seq(ref("binaryExpression")).plus());
    def("keywordMethod", ref("keywordToken")
        .seq(ref("variable")).plus());
    def("keywordPragma", ref("keywordToken")
        .seq(ref("arrayItem")).plus());
    def("keywordToken", token(ref("keyword")));
    def("literal", ref("numberLiteral")
        .or(ref("stringLiteral"))
        .or(ref("charLiteral"))
        .or(ref("arrayLiteral"))
        .or(ref("byteLiteral"))
        .or(ref("symbolLiteral"))
        .or(ref("nilLiteral"))
        .or(ref("trueLiteral"))
        .or(ref("falseLiteral")));
    def("message", ref("keywordMessage")
        .or(ref("binaryMessage"))
        .or(ref("unaryMessage")));
    def("method", ref("methodDeclaration")
        .seq(ref("methodSequence")));
    def("methodDeclaration", ref("keywordMethod")
        .or(ref("unaryMethod"))
        .or(ref("binaryMethod")));
    def("methodSequence", ref("periodToken").star()
        .seq(ref("pragmas"))
        .seq(ref("periodToken").star())
        .seq(ref("temporaries"))
        .seq(ref("periodToken").star())
        .seq(ref("pragmas"))
        .seq(ref("periodToken").star())
        .seq(ref("statements")));
    def("multiword", ref("keyword").plus());
    def("nilLiteral", ref("nilToken"));
    def("nilToken", token("nil")
        .seq(word().not()));
    def("numberLiteral", ref("numberToken"));
    def("numberToken", token(ref("number")));
    def("parens", token("(")
        .seq(ref("expression"))
        .seq(token(")")));
    def("period", of('.'));
    def("periodToken", token(ref("period")));
    def("pragma", token("<")
        .seq(ref("pragmaMessage"))
        .seq(token(">")));
    def("pragmaMessage", ref("keywordPragma")
        .or(ref("unaryPragma"))
        .or(ref("binaryPragma")));
    def("pragmas", ref("pragma").star());
    def("primary", ref("literal")
        .or(ref("variable"))
        .or(ref("block"))
        .or(ref("parens"))
        .or(ref("array")));
    def("return", token("^")
        .seq(ref("expression")));
    def("sequence", ref("temporaries")
        .seq(ref("periodToken").star())
        .seq(ref("statements")));
    def("start", ref("startMethod"));
    def("startMethod", ref("method").end());
    def("statements", ref("expression")
        .seq(ref("periodToken").plus().seq(ref("statements"))
            .or(ref("periodToken").star()))
        .or(ref("return").seq(ref("periodToken").star()))
        .or(ref("periodToken").star()));
    def("string", of('\'')
        .seq(of("''").or(pattern("^'")).star())
        .seq(of('\'')));
    def("stringLiteral", ref("stringToken"));
    def("stringToken", token(ref("string")));
    def("symbol", ref("unary")
        .or(ref("binary"))
        .or(ref("multiword"))
        .or(ref("string")));
    def("symbolLiteral", token("#").plus()
        .seq(token(ref("symbol"))));
    def("symbolLiteralArray", token(ref("symbol")));
    def("temporaries", token("|")
        .seq(ref("variable").star())
        .seq(token("|"))
        .optional());
    def("trueLiteral", ref("trueToken"));
    def("trueToken", token("true")
        .seq(word().not()));
    def("unary", ref("identifier")
        .seq(of(':').not()));
    def("unaryExpression", ref("primary")
        .seq(ref("unaryMessage").star()));
    def("unaryMessage", ref("unaryToken"));
    def("unaryMethod", ref("identifierToken"));
    def("unaryPragma", ref("identifierToken"));
    def("unaryToken", token(ref("unary")));
    def("variable", ref("identifierToken"));
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy