From 732ef5e9787e618ead3a18f9f6aa2ed1f03f1670 Mon Sep 17 00:00:00 2001 From: Melody Horn Date: Wed, 14 Oct 2020 17:44:38 -0600 Subject: throw early draft of parser into the world --- crowbar_reference_compiler/parser.py | 200 +++++++++++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 crowbar_reference_compiler/parser.py (limited to 'crowbar_reference_compiler/parser.py') diff --git a/crowbar_reference_compiler/parser.py b/crowbar_reference_compiler/parser.py new file mode 100644 index 0000000..9bb3179 --- /dev/null +++ b/crowbar_reference_compiler/parser.py @@ -0,0 +1,200 @@ +from parsimonious import TokenGrammar, ParseError, IncompleteParseError # type: ignore + +grammar = TokenGrammar( + r""" +HeaderFile = HeaderFileElement+ +HeaderFileElement = IncludeStatement / + TypeDeclaration / + FunctionDeclaration + +ImplementationFile = ImplementationFileElement+ +ImplementationFileElement = HeaderFileElement / + FunctionDefinition + +IncludeStatement = "include" string_literal ";" + +TypeDeclaration = StructDeclaration / + EnumDeclaration / + TypedefDeclaration +StructDeclaration = "struct" identifier "{" VariableDeclaration+ "}" ";" +EnumDeclaration = "enum" identifier "{" EnumBody "}" ";" +EnumBody = (identifier ("=" Expression)? "," EnumBody) / + (identifier ("=" Expression)? ","?) +TypedefDeclaration = "typedef" identifier "=" Type ";" + +FunctionDeclaration = FunctionSignature ";" +FunctionDefinition = FunctionSignature Block +FunctionSignature = Type identifier "(" SignatureArguments? ")" +SignatureArguments = (Type identifier "," SignatureArguments) / + (Type identifier ","?) + +Block = "{" Statement* "}" + +Statement = VariableDefinition / + VariableDeclaration / + IfStatement / + SwitchStatement / + WhileStatement / + DoWhileStatement / + ForStatement / + FlowControlStatement / + AssignmentStatement / + ExpressionStatement + +VariableDefinition = Type identifier "=" Expression ";" +VariableDeclaration = Type identifier ";" + +IfStatement = ("if" Expression Block "else" Block) / + ("if" Expression Block) + +SwitchStatement = "switch" Expression "{" SwitchCase+ "}" +SwitchCase = (CaseSpecifier Block) / + ("default" Block) +CaseSpecifier = ("case" Expression "," CaseSpecifier) / + ("case" Expression ","?) + +WhileStatement = "while" Expression Block +DoWhileStatement = "do" Block "while" Expression ";" +ForStatement = "for" VariableDefinition? ";" Expression ";" AssignmentStatementBody? Block + +FlowControlStatement = ("continue" ";") / + ("break" ";") / + ("return" Expression? ";") + +AssignmentStatement = AssignmentStatementBody ";" +AssignmentStatementBody = (AssignmentTargetExpression "=" Expression) / + (AssignmentTargetExpression "+=" Expression) / + (AssignmentTargetExpression "-=" Expression) / + (AssignmentTargetExpression "*=" Expression) / + (AssignmentTargetExpression "/=" Expression) / + (AssignmentTargetExpression "%=" Expression) / + (AssignmentTargetExpression "&=" Expression) / + (AssignmentTargetExpression "^=" Expression) / + (AssignmentTargetExpression "|=" Expression) / + (AssignmentTargetExpression "++") / + (AssignmentTargetExpression "--") + +ExpressionStatement = Expression ";" + +Type = ("const" BasicType) / + (BasicType "*") / + (BasicType "[" Expression "]") / + (BasicType "function" "(" (BasicType ",")* ")") / + BasicType +BasicType = "void" / + IntegerType / + ("signed" IntegerType) / + ("unsigned" IntegerType) / + "float" / + "double" / + "bool" / + ("struct" identifier) / + ("enum" identifier) / + ("typedef" identifier) / + ("(" Type ")") +IntegerType = "char" / + "short" / + "int" / + "long" + +AssignmentTargetExpression = identifier ATEElementSuffix* +ATEElementSuffix = ("[" Expression "]") / + ("." identifier) / + ("->" identifier) + +AtomicExpression = identifier / + constant / + string_literal / + ("(" Expression ")") + +ObjectExpression = (AtomicExpression ObjectSuffix*) / + ArrayLiteralExpression / + StructLiteralExpression +ObjectSuffix = ("[" Expression "]") / + ("(" CommasExpressionList? ")") / + ("." identifier) / + ("->" identifier) +CommasExpressionList = (Expression "," CommasExpressionList) / + (Expression ","?) +ArrayLiteralExpression = "{" CommasExpressionList "}" +StructLiteralExpression = "{" StructLiteralBody "}" +StructLiteralBody = (StructLiteralElement "," StructLiteralBody?) / + (StructLiteralElement ","?) +StructLiteralElement = "." identifier "=" Expression + +FactorExpression = ("(" Type ")" FactorExpression) / + ("&" FactorExpression) / + ("*" FactorExpression) / + ("+" FactorExpression) / + ("-" FactorExpression) / + ("~" FactorExpression) / + ("!" FactorExpression) / + ("sizeof" FactorExpression) / + ("sizeof" Type) / + ObjectExpression + +TermExpression = FactorExpression TermSuffix* +TermSuffix = ("*" FactorExpression) / + ("/" FactorExpression) / + ("%" FactorExpression) + +ArithmeticExpression = TermExpression ArithmeticSuffix* +ArithmeticSuffix = ("+" TermExpression) / + ("-" TermExpression) + +BitwiseOpExpression = (ArithmeticExpression "<<" ArithmeticExpression) / + (ArithmeticExpression ">>" ArithmeticExpression) / + (ArithmeticExpression "^" ArithmeticExpression) / + (ArithmeticExpression ("&" ArithmeticExpression)+) / + (ArithmeticExpression ("|" ArithmeticExpression)+) / + ArithmeticExpression + +ComparisonExpression = (BitwiseOpExpression "==" BitwiseOpExpression) / + (BitwiseOpExpression "!=" BitwiseOpExpression) / + (BitwiseOpExpression "<=" BitwiseOpExpression) / + (BitwiseOpExpression ">=" BitwiseOpExpression) / + (BitwiseOpExpression "<" BitwiseOpExpression) / + (BitwiseOpExpression ">" BitwiseOpExpression) / + BitwiseOpExpression + +Expression = (ComparisonExpression ("&&" ComparisonExpression)+) / + (ComparisonExpression ("||" ComparisonExpression)+) / + ComparisonExpression + +identifier = "identifier" +constant = "constant" +string_literal = "string_literal" +""") + + +class LegibleParseError(ParseError): + def line(self): + return "🤷" + + def column(self): + return "🤷" + + +class LegibleIncompleteParseError(IncompleteParseError): + def line(self): + return "🤷" + + def column(self): + return "🤷" + + +def parse_from_rule(rule, tokens): + try: + return rule.parse(tokens) + except IncompleteParseError as error: + raise LegibleIncompleteParseError(error.text, error.pos, error.expr) + except ParseError as error: + raise LegibleParseError(error.text, error.pos, error.expr) + + +def parse_header(tokens): + return parse_from_rule(grammar['HeaderFile'], tokens) + + +def parse_implementation(tokens): + return parse_from_rule(grammar['ImplementationFile'], tokens) -- cgit v1.2.3