| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| |
| #include "Builtin.h" |
| #include <stdarg.h> |
| #include <stdlib.h> |
| |
| #define ref(name) ExpressionNewValue(IdentExpr,name) |
| #define seq(...) makeExpression(SequenceExpr,__VA_ARGS__,NULL) |
| #define choice(...) makeExpression(ChoiceExpr,__VA_ARGS__,NULL) |
| #define and(...) makeExpression(AndExpr,__VA_ARGS__,NULL) |
| #define not(...) makeExpression(NotExpr,__VA_ARGS__,NULL) |
| #define opt(...) makeExpression(OptExpr,__VA_ARGS__,NULL) |
| #define star(...) makeExpression(StarExpr,__VA_ARGS__,NULL) |
| #define plus(...) makeExpression(PlusExpr,__VA_ARGS__,NULL) |
| #define lit(value) ExpressionNewValue(LitExpr,value) |
| #define cls(...) makeExpression(ClassExpr,__VA_ARGS__,NULL) |
| #define dot() makeExpression(DotExpr,NULL) |
| #define range(lo,hi) ExpressionNewRange(lo,hi) |
| |
| static Expression *makeExpression(ExprKind kind, ...) |
| { |
| Expression *children[20]; |
| int count = 0; |
| va_list ap; |
| va_start(ap,kind); |
| Expression *expr; |
| while ((count < 20) && ((expr = va_arg(ap,Expression *)) != NULL)) |
| children[count++] = expr; |
| va_end(ap); |
| return ExpressionNew(kind,count,children); |
| } |
| |
| Grammar *GrammarNewBuiltin(void) |
| { |
| Grammar *gram = GrammarNew(); |
| |
| // Grammar <- Spacing Definition+ EndOfFile |
| GrammarDefine(gram,"Grammar", |
| seq(ref("Spacing"), |
| plus(ref("Definition")), |
| ref("EndOfFile"))); |
| |
| // Definition <- Identifier LEFTARROW Expression |
| GrammarDefine(gram,"Definition", |
| seq(ref("Identifier"), |
| ref("LEFTARROW"), |
| ref("Expression"))); |
| // Expression <- Sequence (SLASH Sequence)* |
| GrammarDefine(gram,"Expression", |
| seq(ref("Sequence"), |
| star(seq(ref("SLASH"),ref("Sequence"))))); |
| |
| // Sequence <- Prefix* |
| GrammarDefine(gram,"Sequence", |
| star(ref("Prefix"))); |
| |
| // Prefix <- (AND / NOT)? Suffix |
| GrammarDefine(gram,"Prefix", |
| seq(opt(choice(ref("AND"), |
| ref("NOT"))), |
| ref("Suffix"))); |
| |
| // Suffix <- Primary (QUESTION / STAR / PLUS)? |
| GrammarDefine(gram,"Suffix", |
| seq(ref("Primary"), |
| opt(choice(ref("QUESTION"), |
| ref("STAR"), |
| ref("PLUS"))))); |
| |
| // Primary <- Identifier !LEFTARROW |
| // / OPEN Expression CLOSE |
| // / Literal |
| // / Class |
| // / DOT |
| GrammarDefine(gram,"Primary", |
| choice(seq(ref("Identifier"),not(ref("LEFTARROW"))), |
| seq(ref("OPEN"),ref("Expression"),ref("CLOSE")), |
| ref("Literal"), |
| ref("Class"), |
| ref("DOT"))); |
| |
| // Identifier <- IdentStart IdentCont* Spacing |
| GrammarDefine(gram,"Identifier", |
| seq(ref("IdentStart"), |
| star(ref("IdentCont")), |
| ref("Spacing"))); |
| |
| // IdentStart <- [a-zA-Z_] |
| GrammarDefine(gram,"IdentStart", |
| cls(range('a','z'), |
| range('A','Z'), |
| range('_','_'))); |
| |
| // IdentCont <- IdentStart |
| // / [0-9] |
| GrammarDefine(gram,"IdentCont", |
| choice(ref("IdentStart"), |
| cls(range('0','9')))); |
| |
| // Literal <- ['] (!['] Char)* ['] Spacing |
| // / ["] (!["] Char)* ["] Spacing |
| GrammarDefine(gram,"Literal", |
| choice(seq(cls(range('\'','\'')), |
| star(seq(not(cls(range('\'','\''))), |
| ref("Char"))), |
| cls(range('\'','\'')), |
| ref("Spacing")), |
| seq(cls(range('"','"')), |
| star(seq(not(cls(range('"','"'))), |
| ref("Char"))), |
| cls(range('"','"')), |
| ref("Spacing")))); |
| |
| // Class <- '[' (!']' Range)* ']' Spacing |
| GrammarDefine(gram,"Class", |
| seq(lit("["), |
| star(seq(not(lit("]")), |
| ref("Range"))), |
| lit("]"), |
| ref("Spacing"))); |
| // Range <- Char '-' Char |
| // / Char |
| GrammarDefine(gram,"Range", |
| choice(seq(ref("Char"), |
| lit("-"), |
| ref("Char")), |
| ref("Char"))); |
| |
| // Char <- '\\' [nrt'"\[\]\\] |
| // / '\\' [0-2] [0-7] [0-7] |
| // / '\\' [0-7] [0-7]? |
| // / !'\\' . |
| GrammarDefine(gram,"Char", |
| choice(seq(lit("\\"), |
| cls(range('n','n'), |
| range('r','r'), |
| range('t','t'), |
| range('\'','\''), |
| range('"','"'), |
| range('[','['), |
| range(']',']'), |
| range('\\','\\'))), |
| seq(lit("\\"), |
| cls(range('0','2')), |
| cls(range('0','7')), |
| cls(range('0','7'))), |
| seq(lit("\\"), |
| cls(range('0','7')), |
| opt(cls(range('0','7')))), |
| seq(not(lit("\\")),dot()))); |
| |
| // LEFTARROW <- '<-' Spacing |
| GrammarDefine(gram,"LEFTARROW",seq(lit("<-"),ref("Spacing"))); |
| |
| // SLASH <- '/' Spacing |
| GrammarDefine(gram,"SLASH",seq(lit("/"),ref("Spacing"))); |
| |
| // AND <- '&' Spacing |
| GrammarDefine(gram,"AND",seq(lit("&"),ref("Spacing"))); |
| |
| // NOT <- '!' Spacing |
| GrammarDefine(gram,"NOT",seq(lit("!"),ref("Spacing"))); |
| |
| // QUESTION <- '?' Spacing |
| GrammarDefine(gram,"QUESTION",seq(lit("?"),ref("Spacing"))); |
| |
| // STAR <- '*' Spacing |
| GrammarDefine(gram,"STAR",seq(lit("*"),ref("Spacing"))); |
| |
| // PLUS <- '+' Spacing |
| GrammarDefine(gram,"PLUS",seq(lit("+"),ref("Spacing"))); |
| |
| // OPEN <- '(' Spacing |
| GrammarDefine(gram,"OPEN",seq(lit("("),ref("Spacing"))); |
| |
| // CLOSE <- ')' Spacing |
| GrammarDefine(gram,"CLOSE",seq(lit(")"),ref("Spacing"))); |
| |
| // DOT <- '.' Spacing |
| GrammarDefine(gram,"DOT",seq(lit("."),ref("Spacing"))); |
| |
| // Spacing <- (Space / Comment)* |
| GrammarDefine(gram,"Spacing",star(choice(ref("Space"),ref("Comment")))); |
| |
| // Comment <- '#' (!EndOfLine .)* EndOfLine |
| GrammarDefine(gram,"Comment", |
| seq(lit("#"), |
| star(seq(not(ref("EndOfLine")), |
| dot())), |
| ref("EndOfLine"))); |
| |
| // Space <- ' ' |
| // / '\t' |
| // / EndOfLine |
| GrammarDefine(gram,"Space", |
| choice(lit(" "), |
| lit("\t"), |
| ref("EndOfLine"))); |
| // EndOfLine <- '\r\n' |
| // / '\n' |
| // / '\r' |
| GrammarDefine(gram,"EndOfLine", |
| choice(lit("\r\n"), |
| lit("\n"), |
| lit("\r"))); |
| |
| // EndOfFile <- !. |
| GrammarDefine(gram,"EndOfFile",not(dot())); |
| |
| return gram; |
| } |