123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398 |
- 'use strict';
- const Char = {
- Digit: Regex(/^[0-9]$/),
- NonZero: Regex(/^[1-9]$/),
- NotDigit: Regex(/^[^0-9]$/),
- Alphabet: Regex(/^[A-Za-z]$/),
- DoubleQuote: $1('"'),
- SingleQuote: $1("'"),
- Dot: $1('.'),
- Semicolon: $1(';'),
- Space: one_of(' ', ' '),
- NotSpace: $_(one_of(' ', ' ')),
- Any: $u(Str, $(s => s.length >= 1)),
- ForbiddenInId: one_of.apply({}, map(
- CR + LF + '`' + `\\'"()[]{}:,.;!~&|+-*%^<>=`,
- // divide "/" is available
- x => x))
- }
- Pattern.PrefixOperator = function (name, operator) {
- check(Pattern.PrefixOperator, arguments, {
- name: Str, operator: Optional(Str)
- })
- operator = operator || name
- return Pattern('Operator', name, map(operator, (char, index) => Unit(
- $1(char), '', (index < operator.length-1)? Any: Char.NotSpace
- )))
- }
- Pattern.TextOperator = function (name, operator) {
- check(Pattern.PrefixOperator, arguments, {
- name: Str, operator: Optional(Str)
- })
- operator = operator || name
- return Pattern('Operator', name, map(operator, (char, index) => Unit(
- $1(char), '', (index < operator.length-1)? Any: Char.Space
- )))
- }
- Pattern.Operator = function (name, operator) {
- check(Pattern.Operator, arguments, {
- name: Str, operator: Optional(Str)
- })
- operator = operator || name
- return Pattern('Operator', name, map(operator, (char, index) => Unit(
- $1(char)
- )))
- }
- const Tokens = [
- Pattern('String', 'RawString', [
- Unit(Char.SingleQuote),
- Unit($_(Char.SingleQuote), '*'),
- Unit(Char.SingleQuote)
- ]),
- Pattern('String', 'FormatString', [
- Unit(Char.DoubleQuote),
- Unit($_(Char.DoubleQuote), '*'),
- Unit(Char.DoubleQuote)
- ]),
- Pattern('RawCode', 'RawCode', [
- Unit($1('/')),
- Unit($1('~')),
- CustomUnit((char, next) => `${char}${next}` != '~/', '*'),
- Unit($1('~')),
- Unit($1('/'))
- ]),
- Pattern('Comment', 'Comment', [
- Unit($1('/')),
- Unit($1('*')),
- CustomUnit((char, next) => `${char}${next}` != '*/', '*'),
- Unit($1('*')),
- Unit($1('/'))
- ]),
- Pattern('Blank', 'Space', [
- Unit($u(Char.Space, one_of(CR, TAB)), '+')
- ]),
- Pattern('Blank', 'Linefeed', [
- Unit($1(LF), '+')
- ]),
- Pattern('Blank', 'Linefeed', [
- Unit(Char.Semicolon, '+')
- ]),
- Pattern.Operator('('),
- Pattern.Operator(')'),
- Pattern.Operator('['),
- Pattern.Operator(']'),
- Pattern.Operator('{'),
- Pattern.Operator('}'),
- Pattern.Operator(','),
- Pattern.Operator(':'),
- Pattern.Operator('.{'),
- Pattern.Operator('..{'),
- Pattern.Operator('...{'),
- Pattern.Operator('.['),
- Pattern.Operator('..['),
- Pattern.Operator('..'), // ..Identifier = Inline Comment
- Pattern.Operator('.'),
- // name of simple operator starts with a capital alphabet
- Pattern.Operator('!='),
- Pattern.PrefixOperator('!'),
- Pattern.Operator('||'),
- Pattern.Operator('&&'),
- Pattern.PrefixOperator('~'),
- Pattern.Operator('|'),
- Pattern.Operator('&'),
- Pattern.Operator('->'),
- Pattern.Operator('<-'),
- Pattern.PrefixOperator('Negate', '-'),
- Pattern.Operator('-'),
- //Pattern.PrefixOperator('Positive', '+'),
- Pattern.Operator('+'),
- Pattern.Operator('**'),
- Pattern.Operator('*'),
- Pattern.Operator('/'),
- //Pattern.PrefixOperator('Parameter', '%'), // ugly, use dot
- Pattern.Operator('%'),
- Pattern.Operator('^'),
- Pattern.Operator('=='),
- Pattern.Operator('=>'),
- Pattern.Operator('='),
- Pattern.Operator('<<'),
- Pattern.Operator('>>'),
- Pattern.Operator('<'),
- Pattern.Operator('>'),
- Pattern.Operator('<='),
- Pattern.Operator('>='),
- Pattern.TextOperator('Is', 'is'),
- Pattern.TextOperator('~', 'not'),
- Pattern('Number', 'Exponent', [
- Unit(Char.Digit, '+'),
- Unit(Char.Dot),
- Unit(Char.Digit, '+'),
- Unit(one_of('E', 'e')),
- Unit(one_of('+', '-'), '?'),
- Unit(Char.Digit, '+')
- ]),
- Pattern('Number', 'Float', [
- Unit(Char.Digit, '+'),
- Unit(Char.Dot),
- Unit(Char.Digit, '+')
- ]),
- Pattern('Number', 'Integer', [
- Unit(Char.Digit, '+')
- ]),
- Pattern('Name', 'Name', [
- Unit($n(Char.NotDigit, Char.NotSpace, $_(Char.ForbiddenInId))),
- Unit($n(Char.NotSpace, $_(Char.ForbiddenInId)), '*')
- ])
- ]
- const SimpleOperand = $n(
- Token.Valid,
- $(token => is(token.matched.name, one_of(
- 'Exponent', 'Float', 'Integer',
- 'RawString', 'FormatString',
- 'Identifier', 'Member'
- ))
- ))
- const SimpleOperator = {
- Sentinel: { type: 'N/A', priority: -1, assoc: 'left' },
- Parameter: { type: 'prefix', priority: 100, assoc: 'right' },
- Access: { type: 'infix', priority: 99, assoc: 'left' },
- Call: { type: 'infix', priority: 98, assoc: 'left' },
- Get: { type: 'infix', priority: 98, assoc: 'left' },
- Is: { type: 'infix', priority: 10, assoc: 'left' },
- Negate: { type: 'prefix', priority: 85, assoc: 'right' },
- '+': { type: 'infix', priority: 50, assoc: 'left' },
- '-': { type: 'infix', priority: 50, assoc: 'left' },
- '*': { type: 'infix', priority: 80, assoc: 'left' },
- '/': { type: 'infix', priority: 70, assoc: 'left' },
- '%': { type: 'infix', priority: 75, assoc: 'left' },
- '^': { type: 'infix', priority: 90, assoc: 'right' },
- '==': { type: 'infix', priority: 30, assoc: 'left' },
- '!=': { type: 'infix', priority: 20, assoc: 'left' },
- '>': { type: 'infix', priority: 20, assoc: 'left' },
- '>=': { type: 'infix', priority: 20, assoc: 'left' },
- '<': { type: 'infix', priority: 20, assoc: 'left' },
- '<=': { type: 'infix', priority: 20, assoc: 'left' },
- '!': { type: 'prefix', priority: 85, assoc: 'right' },
- '&&': { type: 'infix', priority: 40, assoc: 'left' },
- '||': { type: 'infix', priority: 30, assoc: 'left' },
- '~': { type: 'prefix', priority: 85, assoc: 'right' },
- '&': { type: 'infix', priority: 40, assoc: 'left' },
- '|': { type: 'infix', priority: 30, assoc: 'left' }
- }
- SetEquivalent(SimpleOperator, $(
- token => has(SimpleOperator, token.matched.name)
- ))
- const KeywordList = ['module', 'export', 'use', 'as', 'import', 'let', 'outer', 'return', 'that', 'for', 'in', 'struct', 'to', 'by', 'f', 'g', 'h', 'global', 'upper', 'local']
- const TokenList = list(new Set(map(Tokens, t => t.name)))
- const Syntax = mapval({
-
- Id: ['Identifier', 'RawString'],
- Constraint: 'Identifier',
-
- Module: 'ModuleName ExportList Program',
- ModuleName: '~module Id',
- ExportList: ['Export NextExport', ''],
- Export: '~export AsList',
- NextExport: ['Export NextExport', ''],
-
- Program: 'Command NextCommand',
- Command: [
- 'Use',
- 'Import',
- 'FunDef',
- 'Let',
- 'Return',
- 'Assign',
- 'Outer',
- 'Expr'
- ],
- NextCommand: ['Command NextCommand', ''],
-
- Use: '~use AsList',
- As: ['Id ~as Id', 'Id'],
- AsList: ['As NextAs', '( As NextAs )'],
- NextAs: [', As NextAs', ''],
- Import: '~import IdList',
- IdList: ['Id NextId', '( Id NextId )'],
- NextId: [', Id NextId', ''],
-
- Let: '~let Id = Expr',
- Assign: 'LeftVal = Expr',
- Outer: '~outer Id = Expr',
- LeftVal: 'Id MemberNext KeyNext',
- MemberNext: ['Access Member MemberNext', ''],
- KeyNext: ['Get Key KeyNext', ''],
-
- Return: '~return Expr',
-
- Expr: [
- 'MapExpr'
- ],
-
- Concept: '{ Id That FilterList }',
- That: ['|', '~that'],
- FilterList: 'Filter NextFilter',
- NextFilter: [', Filter NextFilter', ''],
- Filter: 'Simple',
-
- For: [':', '~for'],
- IteratorExpr: [
- '.[ MapOperand For ListExprArgList ListExprFilterList ]'
- ],
- ListExpr: [
- '[ MapOperand For ListExprArgList ListExprFilterList ]'
- ],
- ListExprFilterList: [', FilterList', ''],
- ListExprArgList: ['ListExprArg NextListExprArg'],
- ListExprArg: ['Id ~in Simple'],
- NextListExprArg: [', ListExprArg NextListExprArg', ''],
-
- PairListExpr: ['[ AdvPair NextAdvPair ]'],
- NextAdvPair: [', AdvPair NextAdvPair', ''],
- AdvPair: 'MapOperand : Expr',
-
- Struct: '~struct Hash',
- FiniteSet: '{ ItemList }',
-
- MapExpr: 'MapOperand MapNext',
- MapNext: [
- 'MapOperator MapOperand MapNext',
- ''
- ],
- MapOperator: [
- '->', '<-',
- '>>', '<<',
- '~to', '~by',
- '**', '=>'
- ],
- MapOperand: [
- 'RawCode',
- 'FiniteSet',
- 'Hash', 'HashLambda',
- 'List', 'ListLambda',
- 'PairListExpr',
- 'SimpleLambda',
- 'BodyLambda',
- 'IteratorExpr',
- 'ListExpr',
- 'FunExpr',
- 'Concept',
- 'Struct',
- 'Simple'
- ],
-
- ItemList: 'Item NextItem',
- Item: 'Expr',
- NextItem: [', Item NextItem', ''],
-
- PairList: 'Pair NextPair',
- Pair: 'Id : Expr',
- NextPair: [', Pair NextPair', ''],
-
- Hash: ['{ }', '{ PairList }'],
- List: [
- '[ ]', 'Get [ ]', // Get operator may be inserted by get_tokens()
- '[ ItemList ]', 'Get [ ItemList ]'
- ],
-
- HashLambda: ['..{ }', '..{ PairList }'],
- ListLambda: ['..[ ]', '..[ ItemList ]'],
-
- SimpleLambda: [
- '.{ LambdaParaList SimpleLambda }',
- '.{ LambdaParaList Simple }'
- ],
-
- BodyLambda: '...{ Program }',
-
- LambdaParaList: [
- '( LambdaPara NextLambdaPara ) ->',
- 'LambdaPara ->',
- ''
- ],
- LambdaPara: ['Identifier'],
- NextLambdaPara: [', LambdaPara NextLambdaPara', ''],
-
- ParaList: ['( )', '( Para NextPara )'],
- Para: 'Constraint PassFlag Id',
- NextPara: [', Para NextPara', ''],
- PassFlag: ['&', '*', ''],
- Target: ['-> Constraint', '->', ''],
- Body: '{ Program }',
-
- FunFlag: ['~g :', '~h :', '~f :', '~global :', '~upper :', '~local :'],
- NoFlag: ['Call', ''],
- FunExpr: [
- 'FunFlag ParaList Target Body',
- 'NoFlag ParaList Target Body'
- ],
-
- Effect: ['~global', '~upper', '~local'],
- FunDef: 'Effect Id Call ParaList Target Body',
- // ↑ call operator will be inserted automatically
-
- //Simple: () => parse_simple,
- Simple: 'Identifier',
- Wrapped: '( Simple )',
- Key: '[ Simple ]',
- ArgList: [
- '( )',
- '( KeyArg NextKeyArg )',
- '( Arg NextArg )'
- ],
- Arg: 'Simple',
- NextArg: [', Arg NextArg', ''],
- KeyArg: 'Id : Simple',
- NextKeyArg: [', KeyArg NextKeyArg', '']
-
- }, function (rule) {
- let split = (string => string? string.split(' '): [])
- let derivations = (array => ({ derivations: array }))
- return transform(rule, [
- { when_it_is: Str, use: d => derivations([split(d)]) },
- { when_it_is: List, use: r => derivations(map(r, d => split(d))) },
- { when_it_is: Otherwise, use: r => r }
- ])
- })
- const PartList = list(cat(
- Object.keys(Syntax), map(KeywordList, x => '~'+x), TokenList,
- ['Call','Get','Identifier']
- ))
- assert(fold(PartList, {}, function (name,state) {
- if (state === false) {
- return false
- } else if(state[name]) {
- console.log(name)
- return false
- } else {
- state[name] = true
- return state
- }
- }))
|